Reputation: 33
I have written the following piece of code in an attempt to provide a type-safe interface:
namespace MWE
{
public abstract class C {}
public class A : C {}
public class B : C {}
public class Container<T> where T : C
{
public readonly T Value;
public static implicit operator T(Container<C> c)
{
return c.Value;
}
}
public interface IWrapper<out TC> where TC : C {}
public class Foo
{
public Foo(IWrapper<Container<C>> wrapper) {}
}
}
Unfortunately this doesn't compile. The Container<C>
-part of the wrapper
parameter to the Foo
constructor causes the compiler to produce the following error:
The type 'MFE.Container<MFE.C>' cannot be used as type parameter 'TC' in the generic type or method 'IWrapper<TC>'. There is no implicit reference conversion from 'MFE.Container<MFE.C>' to 'MFE.C'.
The type 'MFE.Container<MFE.C>' must be convertible to 'WeirdTestStuff.C' in order to use it as parameter 'TC' in the generic interface 'MFE.IWrapper<out TC>'.
I can't figure out where the problem is exactly, since the Covariance for the conversion seems to be there and there is even an implicit conversion from a Container<T>
to T
defined. Since T : C
, I assumed it should just work like this.
I'd like to keep Foo
's constructor as is if possible.
I hope someone can point me to a solution of this problem
Upvotes: 3
Views: 1253
Reputation: 239824
even an implicit conversion from a Container to T defined
That is true but that's not what the compiler requires. It requires:
implicit reference conversion
(My emphasis)
An implicit reference conversion is not one supplied by any user-defined operator and is allowed only when one type derives (directly or via intermediate types) from the other1.
Container
has-a C
and can be converted to a C
via a user-defined operator but that's not enough to make it be-a C. Your question is too abstracted to say what the fix should be here - should Container
be non-generic and derived from C
? That's the obvious way to "shut up" the compiler but may not solve your actual problem.
You can't use generics to make a type's base-type settable at runtime.
1These are Eric Lippert's Representation-preserving conversions
Upvotes: 3