0

From C# 4.0 Spec section 6.1.6:

The implicit reference conversions are:

[...]

From any reference-type to an interface or delegate type T if it has an implicit identity or reference conversion to an interface or delegate type T0 and T0 is varience-convertible (13.1.3.2) to T.

Vladimir Reshetnikov tells us that there is an implicit reference conversion from List<string> to IEnumerable<object>. But, how can I apply this to a user defined type (is it even possible)?

I tried an implicit operator, custom derived types and a few varitions there-of...but I cannot reproduce the scenerio. I have:

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<object> specialClassConversion = new List<string>();
        IEnumerable<A> userdefinedTypeConversion = new List<B>();
        A implicitConversion = new B();//varience-convertible
        IC<A> explicitConversion = (IC<A>)new D<B>();//OK, varience-convertible
        IC<A> implicitConversion2 = new D<B>();//does not compile
    }
}

class A { }

class B : A { }

interface IC<T> { }    

class D<T> 
{
    //public static implicit operator IC(D<T> m)//Error: user-defined conversions to or from an interface are not allowed
    //{
    //    return null;
    //}
}
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348

1 Answers1

3

If you want a user-defined class or struct to be implicitly convertible to an interface, let your class/struct implement that interface.

(Edit)

And if you want IC<B> to be implicitly convertible to IC<A>, make the IC<T> interface covariant in T by specifying the out keyword, interface IC<out T> { }. The quote from the spec you gave tells that the "composition" of these two implicit conversion is also an implicit conversion.

Source:

interface IC<out T> {  }

class D<T> : IC<T>  { }

(End edit)

Regarding the List<string> class, it implements IEnumerable<string> which in turn is convertible (implicitly) to IEnumerable<object> because IEnumerable<out T> is covariant (out) in T.

(One reason why they didn't allow you to make a public static implicit operator which converts to/from the interface, is that somone could write a derived class which inherited from your class and implemented the interface. That would give a "natural" conversion between their class and the interface, but the public static implicit operator would also apply, leading to two conversions (one "natural" and one "user-defined") between the types, which would be confusing and ambiguous.)

P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • Can you demostrate how this works with the code in the OP? I tried implementing the interface and ran into various other implementation problems...one is noted in the comments in the OP. – P.Brian.Mackey Feb 08 '13 at 22:14
  • @P.Brian.Mackey If you mean to make your interface covariant like `IEnumerable<>`, write `interface IC { }` (note the **`out`**). Be sure to have `D` implement the interface: `class D : IC { }` The "variance-convertible" stuff of the quote from the spec, is about covariance and contravariance, and in your code sample, use covariance. – Jeppe Stig Nielsen Feb 08 '13 at 22:24
  • 2
    The only way to make a conversion that involves an interface type is to make a conversion in class `C` from `C` to `T`, and then construct `C`. The code to deal with that situation in the compiler get my vote for the most arcane and difficult code in the compiler, and the specification is very difficult to read. Getting Roslyn to match some semblance of both the specification and the previous compiler was one of the toughest challenges in the Roslyn semantic analysis effort. – Eric Lippert Feb 08 '13 at 23:19
  • @EricLippert I tried it out with the Visual C# 5.0 compiler. It looks like in that case the conversion to `IFoo` is never considered. In the "Related" column on the right I found this question about it: [C# compiler bug? Why doesn't this implicit user-defined conversion compile?](http://stackoverflow.com/questions/1208796/) – Jeppe Stig Nielsen Feb 09 '13 at 16:14
  • @EricLippert 's post helped me understand a subtle covarient issue that I missed in this case: http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx – P.Brian.Mackey Feb 09 '13 at 16:48