考虑以下课程:
public class DerivedClassPool<TBase> where TBase : class
{
public TBase Get(Type componentType)
{
// Not important, but you get the idea
return Activator.CreateInstance(componentType) as TBase;
}
public TDerived SomeMethod<TDerived>() where TDerived : TBase
{
return Get(typeof(TBase)) as TDerived;
}
}
请注意,我已将TBase
泛型类参数限制为类:where TBase : class
我还将TDerived
泛型方法参数限制为TBase
或从中派生的内容:where TDerived : TBase
。
我在as TDerived
行收到错误:
类型参数'TDerived'不能与'as'运算符一起使用,因为它没有类类型约束,也没有'class'约束
我明白为了防止错误,我需要添加约束class
,所以我得到:
where TDerived : class, TBase
为什么在TBase
已被限制为某个类且TDerived
被约束为TBase
或从中派生出来时,我必须这样做?
答案 0 :(得分:8)
更新:这个问题是the subject of my blog on September 19th, 2011。谢谢你提出的好问题!
为什么我必须在TBase被限制为类并且TDerived被限制为TBase或从中衍生出来时必须这样做?
因为值类型可以从引用类型派生。 int
派生自引用类型object
和System.ValueType
,并实现了许多接口。这不会使int
成为引用类型。
在SomeMethod<int>
的实例上调用DerivedClassPool<object>
是完全合法的,因为int是从对象派生的。
现在,是的情况,你的批评是有道理的。可以构造这样的情况,其中两个类型参数以这样的方式相关,即它们在逻辑上都只能是引用类型,但是其中只有一个被语言分类为“已知为引用类型”。
作为读者的练习:你能找到一个吗?可能有必要仔细阅读规范的第10.1.5节,以获得“已知为参考类型”的精确定义。
答案 1 :(得分:2)
因为TBase
可以是一个界面,因此TDerived
可以是值类型。