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> ();
}
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>();
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.
No, however it is possible to provide custom CastUp
/ CastDown
methods to achieve this. ImmutableArray<T>
, part of the .NET BCL, does this.