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

本文关键字:函数 泛型类 编译 | 更新日期: 2023-09-27 18:10:27

下面的代码可以在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'的定义,并且无法找到接受'T'类型的第一个参数的扩展方法'Name'(您是否缺少using指令或程序集引用?)

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

您需要对泛型类型T施加约束-否则编译器如何知道它?

生成一个Ifoo,然后

do_something<T>(T t) where T : IFoo  
interface IFoo
{
    string Name {get;set;}
}

不,这段代码将不能在c#中工作,因为没有什么约束类型T具有称为Name的属性。c#中的模板与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;
}

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

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

这是将传入的类型限制为类型Foo或从它派生的任何类型。