是的,如果你知道泛型类型的占位符T
实现了从基类或接口的成员,您可以使用where
条款约束型T
该基类或接口。
public interface IFooable
{
void Foo();
}
// ...
public class Foo<T> where T : IFooable
{
private T _t;
// ...
public void DoFoo()
{
_t.Foo(); // works because we constrain T to IFooable.
}
}
这使得一般类型占位符T
到被视为IFooable
。如果你做而不是限制泛型中的泛型类型占位符,那么它被限制为object
这意味着只有object
的成员对泛型可见(即,你只能看到对object
引用可见的成员,但调用任何被覆盖的成员将调用适当的覆盖)。
注:这是另外很重要的,因为事情像运算符重载(记住,符重载,未覆盖),所以如果你有这样的代码:
public bool SomeSuperEqualsChecker<T>(T one, T two)
{
return one == two;
}
这将始终使用object
的==
即使T
是string
。然而,如果我们有:
public bool SomeSuperEqualsChecker<T>(T one, T two)
{
// assume proper null checking exists...
return one.Equals(two);
}
这与string
因为Equals()
被覆盖,不超载正常工作。
所以,长和短只是记住一个无约束的通用占位符确实代表任何类型,但唯一可见的调用和操作是那些在object
上可见的调用和操作。
除了接口/基类的限制,也有一些其他方面的限制:
new()
- 意思是说,泛型类型的占位符必须有一个默认的构造函数
class
- 意思是说,泛型类型的占位符必须是引用类型
struct
- 意思是一般类型的占位符必须是一个值类型(枚举,原始的,结构等)
例如:
public class Foo<T> where T : new()
{
private T _t = new T(); // can only construct T if have new() constraint
}
public class ValueFoo<T> where T : struct
{
private T? _t; // to use nullable, T must be value type, constrains with struct
}
public class RefFoo<T> where T : class
{
private T _t = null; // can only assign type T to null if ref (or nullable val)
}
希望这会有所帮助。
+1很好的答案! – Yuck 2011-12-23 22:23:49