D. A.
D. A.

Reputation: 33

"no implicit reference conversion" even though conversion is defined

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

Answers (1)

Damien_The_Unbeliever
Damien_The_Unbeliever

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

Related Questions