Implicitly convert common to shell

I would like to automatically transfer the value to the general container when returning (I know that this is not always desirable, but it makes sense for my case). For example, I would like to write:

public static Wrapper<string> Load() { return ""; } 

I can do this by adding the following to the Wrapper class:

 public static implicit operator Wrapper<T>(T val) { return new Wrapper<T>(val); } 

Unfortunately, this fails when I try to convert IEnumerable , the full code here (and in ideone ):

 public class Test { public static void Main() { string x = ""; Wrapper<string> xx = x; string[] y = new[] { "" }; Wrapper<string[]> yy = y; IEnumerable<string> z = new[] { "" }; Wrapper<IEnumerable<string>> zz = z; // (!) } } public sealed class Wrapper<T> { private readonly object _value; public Wrapper(T value) { this._value = value; } public static implicit operator Wrapper<T>(T val) { return new Wrapper<T>(val); } } 

Compilation Error:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to '...Wrapper<System.Collections.Generic.IEnumerable<string>>'

What exactly is happening, and how can I fix it?

+6
source share
1 answer

The reason is part of the C # specification, as noted in this answer :

A class or structure is allowed to declare a conversion from a source of type S to a target type of T, provided that all of the following statements:

  • ...
  • Neither S nor T are object or interface.

and

Custom conversions are not allowed to convert from or to an interface-type. In particular, this restriction ensures that no user conversions occur when converting to an interface type, and that switching to an interface type is successful only if the actually converted object implements the specified Interface type.

A source

Your implicit conversion works differently when used, for example, in the following code:

 using System; using System.Collections.Generic; public class Wrapper<T> { public T Val { get; private set; } public Wrapper(T val) { Val = val; } public static implicit operator Wrapper<T>(T val) { return new Wrapper<T>(val); } } public class Test { public static Wrapper<IEnumerable<int>> GetIt() { // The array is typed as int[], not IEnumerable<int>, so the // implicit operator can be used. return new int[] { 1, 2, 3 }; } public static void Main() { // Prints 1, 2, 3 foreach (var i in GetIt().Val) { Console.WriteLine(i); } } } 

The specific problem you're working with is that you save your array in a local variable IEnumerable<string> before returning it. This is the type of variable passed into the implicit statement that matters: since the source type S is IEnumerable<int> for your local variable, the statement cannot be used. int[] not an interface, so it works.

+5
source

All Articles