在编译时将泛型类传递给函数
本文关键字:函数 泛型类 编译 | 更新日期: 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或从它派生的任何类型。