Search code examples
c#arrayscompiler-errorsimplicit-conversionimplicit-typing

Can you explain why does the compiler report an error CS0826?


When I tried to create an implicitly typed array I got this error.

I tried to compile this code:

public class Bad
{
    public static implicit operator Good(Bad bad)
    {
        return new Good();
    }
}

public class Good
{
    public static implicit operator Bad(Good good)
    {
        return new Bad();
    }
}

class Program
{
    static void Main()
    {
        var array = new[] { new Good(), new Bad() };
    }
}

I know the reason of the error: the compiler can't choose the specific type and I should cast some object of array to type of another object and it'll be work in this case, but could someone explain why the compiler doesn't cast the array to type Good or Bad randomly?

Because it'll be useless? Or because it might works wrong in further code? Why half my newbie intuition says it may be useful?


Solution

  • If you don't provide an explicit type for the array, the compiler is going to try and infer the type based on the elements. If you do something like this

    var arr = new [] { 1, 2, 3 };
    

    Because all the elements are the same type, the array is the type of all the elements.

    If you have something like this

    var arr = new[] { 1.1, 2.2, 3, 4.4 };
    

    The compiler sees that not all the elements are the same type, but there is exactly one path the compiler can take where all elements are implicitly converted (or left alone) into the same type - a double, thus the array is a double and the third element is implicitly cast into a double.

    With your example, the compiler sees that not all elements are the same explicit type, so it looks through all the possible implicit conversions. Because there are more than one path it could take (Bad element -> Good, and Good element -> Bad), it throws its hands up because it doesn't know what to do. The choice is ambiguous. There is no "best type" to choose because both options are equally viable for the compiler.

    However, for you, the programmer, what type the array variable becomes will affect the rest of your code, so it needs to be a pre-determined decision.

    There's two ways to fix this:

    1. Remove the implicit operator from either Good or Bad. This reduces the implicit paths the compiler can take to just 1.
    2. Tell the compiler your intention.
      var array = new Good[] { new Good(), new Bad() };
      // or
      var array = new Bad[] { new Good(), new Bad() };