Covariance for generic classes

2020-07-24 04:04发布

Is there any way in C# to achieve the following:

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条回答
The star\"
2楼-- · 2020-07-24 04:20

In C# only interfaces can be variant. Quoting C# spec:

Variant type parameter lists can only occur on interface and delegate types.

So you could declare a generic, covariant interface IBaseClass<out T>, make BaseClass<T> implement it, and later on cast to IBaseClass<BaseTypeInner> instead of casting to the class.

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>();
查看更多
女痞
3楼-- · 2020-07-24 04:23

No, however it is possible to provide custom CastUp / CastDown methods to achieve this. ImmutableArray<T>, part of the .NET BCL, does this.

查看更多
倾城 Initia
4楼-- · 2020-07-24 04:39

A possible solution is to have a base type for the base generic type:

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

But, that's not a good idea because I'm using a lower class that's not generic so I'm losing all the details and restrictions I get from using type parameters.

查看更多
登录 后发表回答