简体   繁体   English

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

[英]Class and Method level generic type constraints interaction

Consider the following class: 考虑以下课程:

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;
    }
}

Note that I've restricted the TBase generic class argument to be a class: where TBase : class 请注意,我已将TBase泛型类参数限制为类: where TBase : class
I've also restricted the TDerived generic method argument to be TBase or something derived from that: where TDerived : TBase . 我还将TDerived泛型方法参数限制为TBase或从中得出的东西: where TDerived : TBase

I get an error on the as TDerived line: 我在as TDerived行上收到错误:

The type parameter 'TDerived' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint 类型参数'TDerived'不能与'as'运算符一起使用,因为它没有类类型约束,也没有'class'约束

I understand that to prevent the error I need to add the constraint class , so I'd get: 我明白为了防止错误,我需要添加约束class ,所以我得到:

where TDerived : class, TBase

Why do I have to do this when TBase is already constrained to be a class and TDerived is constrained to be a TBase or derived from it? TBase已被限制为类并且TDerived被限制为TBase或从中衍生时,为什么必须这样做呢?

UPDATE: This question was the subject of my blog on September 19th, 2011 . 更新:这个问题是我的博客2011年9月19日的主题 Thanks for the great question! 谢谢你这个好问题!


Why do i have to do this when TBase is already constrained to be a class and TDerived is constrained to be a TBase or derived from it? 当TBase已被限制为类并且TDerived被限制为TBase或从中衍生时,为什么我必须这样做?

Because a value type can be derived from a reference type. 因为值类型可以从引用类型派生。 int is derived from reference types object and System.ValueType and implements a number of interfaces. int派生自引用类型objectSystem.ValueType并实现了许多接口。 That doesn't make int a reference type. 这不会使int成为引用类型。

It is perfectly legal for you to call SomeMethod<int> on an instance of DerivedClassPool<object> because int is derived from object. DerivedClassPool<object>的实例上调用SomeMethod<int>是完全合法的,因为int是从object派生的。

Now, there are cases where your criticism would be warranted. 现在, 您的批评是必要的情况下。 One can construct situations in which two type parameters are related in such a way that both of them logically can only be reference types, but only one of them is classified by the language as "known to be of reference type". 可以构造这样的情况,其中两个类型参数以这样的方式相关,即它们在逻辑上都只能是引用类型,但是其中只有一个被语言分类为“已知为引用类型”。

As an exercise to the reader: can you find one? 作为读者的练习:你能找到一个吗? It might be necessary to carefully read section 10.1.5 of the specification for a precise definition of "known to be a reference type". 可能有必要仔细阅读规范的第10.1.5节,以获得“已知为参考类型”的精确定义。

因为TBase可能是一个接口,因此TDerived可能是一种值类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM