Search code examples
c#interfacecastingupcasting

Why won't upcast to concrete type of another common interface


Why can't you upcast to a different concrete type of another common interface. I've created this example in linqpad. Now I can understand if you had different properties between the two classes that an up cast would fail because it couldn't complete the object. But in this Scenario I don't see why the upcast would fail.

void Main()
{
    ICommon test = new ConcreteA();

    ((ConcreteA)test).a.Dump();

    // this errors with: Unable to cast object of type 'ConcreteA' to type 'ConcreteB'.
    ((ConcreteB)test).a.Dump();
}

public interface ICommon
{
   string a {get; }
}

public class ConcreteA : ICommon
{
    public string a {
        get{ return "Concrete A"; }
    }
}

public class ConcreteB : ICommon
{
    public string a {
        get{ return "Concrete B"; }
    }
}

Shouldn't the compiler be able to treat this as if you were casting from an double to an int, if a double was too big for an int it would throw an exception but if the cast was possible the compiler would do it. Why doesn't the compiler try to load the ConcreteA as a ConcreteB and if there were extra properties in the ConcreteB that it couldn't figure out then it would throw.


Solution

  • Since ConcreteA knows nothing about ConcreteB (in your case, because they may have different implementation for property a), I suggest you implement explicit operator for ConcreteB like this:

    public class ConcreteA
    {
        /* rest of your code ... */
    
        public static explicit operator ConcreteB(ConcreteA instance)
        {
            // implement converting from ConcreteA to ConcreteB
        }
    }
    

    For more info about explicit operator: https://msdn.microsoft.com/en-us/library/xhbhezf4.aspx