在编译时将泛型类传递给函数

时间:2013-04-23 18:06:29

标签: c# generics

以下代码是否适用于c#?

public class Foo
{
    public string Name { get; set; }
}

public class Related_Foo
{
    public string Name { get; set; }
}

class Program
{
    static void do_something<T>(T t)
    {
        string n = t.Name;
    }

    static void Main(string[] args)
    {
        Foo f = new Foo();

        do_something(f);
    }
}

在.Net 4中,编译器抱怨:

'T'不包含'Name'的定义,也没有扩展方法'Name'接受类型'T'的第一个参数(你是否缺少using指令或汇编引用?)

3 个答案:

答案 0 :(得分:3)

您需要对泛型类型T设置约束 - 否则编译器应该如何知道呢?

制作Ifoo,然后

do_something<T>(T t) where T : IFoo  

interface IFoo
{
    string Name {get;set;}
}

答案 1 :(得分:0)

不,此代码在C#中不起作用,因为没有任何限制类型T具有名为Name的属性。 C#中的模板与C ++中的模式不同,编译器可以在编译时扩展它们并验证实际使用的某些成员是否存在。

要使其工作,您可以添加T必须属于具有名为name的属性的类型的约束。例如,创建一个接口:

public interface IFoo
{
    string Name { get; }
}

让您的类实现此接口。

然后将约束添加到您的方法中,如下所示:

static void do_something<T>(T t) where T : IFoo
{
    string n = t.Name;
}

如果所有类都有一个具有属性Name的公共基类,例如Related_Foo来自Foo,那么您可以将其约束为类类型,相同的语法:

static void do_something<T>(T t) where T : Foo
{
    string n = t.Name;
}

答案 2 :(得分:0)

如果do_something应该总是使用Foo或从Foo派生的任何东西(而不是总是有一个名为Name的属性),你可以这样做:

 static void do_something<T>(T t) where T : Foo
 {
      string n = t.Name;
 }

这会将传入的Type约束为Type Foo或从中派生的任何类型。