是的,如果你知道泛型類型的佔位符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