我可以使用泛型来获取传递结构的属性吗?

时间:2016-07-28 11:50:54

标签: c# generics

我正在尝试使用Generics将结构传递给函数,然后让该函数访问其属性。我想更多地利用泛型,因为它们应该是安全和高效的#34;。这是我的代码的样子。

班级

class foo { 
    struct A { 
       int a;
       int b
    }

    struct B {
       int a;
       int b;
    } 
}

通用功能

void bar<T> (T input) {
    var a = input.a;       //this is where its says it know nothing about a
}

函数调用

bar<foo.A> (Aobj);

可以像这样使用泛型吗?(那就是访问对象的数据成员......) 或者我能做的就是创建一个过载的方法?我试图从函数中访问的对象的唯一部分对于这两种类型都是通用的,因此我也认为我可以使用泛型。

4 个答案:

答案 0 :(得分:3)

使用泛型并不意味着您可以使用duck typing。 C#是一种静态类型语言,因此您需要执行以下操作:

首先,定义一个定义AB的公共接口的接口:

interface IHasAB
{
    int A { get; }
    int B { get; }
}

然后,让您的struct实现此界面:

struct A : IHasAB
{
    public A(int a, int b)
    {
        A = a;
        B = b;
    }

    public int A { get; }  // Note: `A` and `B` are now properties, not fields
    public int B { get; }  // like before; interfaces do not allow you to declare fields.

    // Note also: mutable structs are a bad idea! That's why we implement
    // `A` and `B` as read-only properties.
}

struct B : IHasAB { … }  // same as for `A`

现在,您可以使用其他泛型类型参数约束bar实现方法where T : IHasAB

void bar<T> (T input) where T : IHasAB
{
    var a = input.A;
}

T上的约束使编译器知道它可以期望T。它现在知道T是一种实现IHasAB的类型,因此有两个属性AB(因为这是接口所包含的)。这就是您现在可以.A访问input的原因。

请注意,您不一定需要bar通用:

void bar(IHasAB input)
{
    var a = input.A;
}

在后一种情况下,请注意input现在是引用类型参数。如果您将AB结构中的一个传递给该方法,则必须将其装箱(即从值类型转换为引用类型)。这涉及到一些开销。

我不会进一步探讨可变结构和拳击的危险,这些结构在结构实现接口的情况下很容易发生,因为这完全是另一回事;我建议您花一点时间研究这些主题。 ; - )

答案 1 :(得分:0)

您需要在访问

之类的成员之前将T强制转换为特定类型
void bar<T> (T input) 
{
    var obj = T as foo;
    if (obj != null)
       var a = obj.A;      
}

答案 2 :(得分:0)

您需要向编译器指定您期望T的类型。您的方法bar<T>完全不了解T,除非必须类型至少类型为objectobject的子类。这意味着您可以使用object T上定义的所有方法。

但是,如果您希望能够使用a,则需要告诉bar<T> T将是一个实现属性a的类型。接口发挥作用的地方。这意味着您需要创建一个超类或更好的界面,这个界面需要a的实现,因此您可以告诉bar<T> T至少是<your interface>类型。请参阅以下代码:

interface ImanInterfaceWithA {
     int a {get; set;}
}

class foo { 
    struct A : ImanInterfaceWithA { 
       public int a {get; set;}
       public int b {get; set;}
    }

    struct B : ImanInterfaceWithA {
       public int a {get; set;}
       public int b {get; set;}
    } 


    void bar<T> (T input) where T : IamanInterfaceWithA
    {
        var a = input.a;
    }
}

答案 3 :(得分:-1)

使用dynamic

void bar<T> (T input) {
    dynamic a = input.a;       //this is where its says it know nothing about a
}