Casting between two types derived from the (same) interface

  1. Types do not derive from an interface. They implement an interface.
  2. The fact that both an Elephant and a Spider are Animals doesn't mean that you can convert one to the other.

You cannot cast or convert from A to B if all they share is a common interface unless you actually define your own conversion operator, assuming you control the source for one of the types, or use another provided user-defined conversion supplied by someone who does control the source. (However, such user-defined conversions would not preserve the original object. One object goes into the conversion, a different object comes out.)

You can convert from A to Interface1, and B to Interface1. But two types simply sharing a common parent does not make those two types convertible to one another.

A a = new A(); 
B b = new B();
Interface1 obj1 = a; // legal
Interface1 obj2 = b; // legal
B obj3 = (B)a; // not legal, a is simply not a B

tobias86 put in well in a comment below, you have a cat and a dog. Both derive from Animal. But a cat just isn't a dog.


As an expansion, you might be struggling with how and why you would use an interface. You do not use an interface to substitute an A for a B, or a B for an A. You use it to substitute either A or B for Interface1. It's the interface you expect, and the A or B you might supply. Given:

public void DoSomething(Interface1 obj) { } // expects 
DoSomething(new A()); // you can supply A

Or

public Interface1 GetSomething() // callers expect to get 
{
    return new B(); // you can supply a B
}

It's the interface you are programming towards, The A and B are merely implementations. You might be thinking you can pass a B to something that expects A. The expectation possibly needs to change.


An object is assignable to an ancestor (direct or indirect base type) or to an interface it implements, but not to siblings (i.e. another type deriving from a common ancestor); however, you can declare your own explicit conversions:

class FooObject : IObject
{
    public string Name { get; set; }
    public int Value { get; set; }

    public static explicit operator FooObject(BarObject bar)
    {
        return new FooObject { Name = bar.Name, Value = bar.Value };
    }
}

class BarObject : IObject
{
    public string Name { get; set; }
    public int Value { get; set; }

    public static explicit operator BarObject(FooObject bar)
    {
        return new BarObject { Name = bar.Name, Value = bar.Value };
    }
}

Now you can write

var foo = new FooObject();
var bar = (BarObject)foo;

or

var bar = new BarObject();
var foo = (FooObject)bar;

without getting errors.

You can also create implicit conversions, if it feels natural. E.g. int is implicitly convertible to double: int i = 5; double x = i;.

(This is also an answer to the closed question How do I cast Class FooObject to class BarObject which both implement interface IObject?).

Tags:

C#

.Net