类和方法级别泛型类型约束交互

时间:2012-01-17 16:48:03

标签: c# generics inheritance

考虑以下课程:

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或从中派生出来时,我必须这样做?

2 个答案:

答案 0 :(得分:8)

更新:这个问题是the subject of my blog on September 19th, 2011。谢谢你提出的好问题!


  

为什么我必须在TBase被限制为类并且TDerived被限制为TBase或从中衍生出来时必须这样做?

因为值类型可以从引用类型派生。 int派生自引用类型objectSystem.ValueType,并实现了许多接口。这不会使int成为引用类型。

SomeMethod<int>的实例上调用DerivedClassPool<object>是完全合法的,因为int是从对象派生的。

现在,的情况,你的批评是有道理的。可以构造这样的情况,其中两个类型参数以这样的方式相关,即它们在逻辑上都只能是引用类型,但是其中只有一个被语言分类为“已知为引用类型”。

作为读者的练习:你能找到一个吗?可能有必要仔细阅读规范的第10.1.5节,以获得“已知为参考类型”的精确定义。

答案 1 :(得分:2)

因为TBase可以是一个界面,因此TDerived可以是值类型。