I have an interface and two types that derive from it.
However, I cannot do the following:
B objectB = (B) objectA
Where B derives
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?).
You need to cast as the interface.
interface IBase { }
class A : IBase { }
class B : IBase { }
With this, the only thing the two types have in common is the interface members. B
might have items that A
does not.
A a = new A();
B b = new B();
IBase aBase = a;
IBase bBase = b;
You can then call anything on the IBase
Interface.
Imagine the following setup:
public interface Human
{
bool Male { get; }
}
public class Man : Human
{
public bool HasABeard { get { return true; } }
public bool IsMale { get { return true; } }
}
public class Woman : Human
{
public bool IsMale { get { return false; } }
public List<Pair<Shoe>> Shoes { get; set; }
}
What would you expect the compiler to produce from the following code? What will the output be?
Man a;
Woman b = new Woman();
a = (Man)b;
Console.WriteLine(a.HasABeard ? "Beard ON" : "Beard OFF");
When casting from A to B B must be a super type for A or the runtime type of the object must be B
that is if you have
class A : B{}
you can cast an object of compile time type A to B. You can also cast a type of B to A if the runtime type of the object is A
in your case the two types does not share super-subtype relationship. They only share a common super type but that's not sufficient.
As an example of why this can't work (generically) how would you have the compiler cast from Point[]
to a Dictionary<string,HashSet<byte>>
? (both implement IEnumerable)
What you want to do doesn't make sense. objectA
is not a B
.
The fact that both types implement the same interface (or have the same base-type, for that matter) does not make them interchangeable; an A
is always an A
, and a B
is always a B
. In an inheritance chain, an object can be cast as itself or any parent type. You have:
A : ISomeInterface
B : ISomeInterface
which lets you cast an A
as A
or ISomeInterface
, and a B
as B
or ISomeInterface
or (depending on your meaning of "derived from")
SomeBaseType
> A
> B
which lets you cast an A
as A
or SomeBaseType
, and a B
as B
or SomeBaseType
(plus object
, in each case)