泛型类的协方差

时间:2015-08-03 22:45:59

标签: c# generics types

C#中是否有任何方法可以实现以下目的:

class MyClass<T>  where T : BaseTypeInner {}

class BaseTypeInner {}

class A : BaseTypeInner {}

class B : BaseTypeInner {}

void Main()
{
    MyClass<BaseTypeInner> variant;

    variant = new MyClass<A> (); // ERROR: Cannot implicitly convert type 'UserQuery.MyClass<UserQuery.A>' to 'UserQuery.MyClass<UserQuery.BaseTypeInner>'

    variant = new MyClass<B> ();
}

3 个答案:

答案 0 :(得分:3)

在C#中,只有接口可以是变体。引用C#规范:

  

变体类型参数列表只能出现在接口和委托类型上。

因此,您可以声明一个通用的协变接口IBaseClass<out T>,让BaseClass<T>实现它,然后转换为IBaseClass<BaseTypeInner>而不是转发给类。

interface IMyClass<out T> where T : BaseTypeInner { }

class MyClass<T> : IMyClass<T> where T : BaseTypeInner { }
IMyClass<BaseTypeInner> variant;

variant = new MyClass<A>(); // works just fine
variant = new MyClass<B>();

答案 1 :(得分:0)

一种可能的解决方案是为基本泛型类型提供基类型:

class BaseType {}

class MyClass<T> : BaseType where T : BaseTypeInner {}

class BaseTypeInner {}

class A : BaseTypeInner {}

class B : BaseTypeInner {}

void Main()
{
    BaseType variant;

    variant = new MyClass<A> ();

    variant = new MyClass<B> ();
}

但是,这并不是一个好主意,因为我使用的是较低级的,并非通用的,所以我失去了使用类型参数获得的所有细节和限制。

答案 2 :(得分:0)

不,但是可以提供自定义CastUp / CastDown方法来实现此目的。 ImmutableArray<T>,.NET BCL的一部分,does this