If I try an invalid cast from a class to an interface, then the compiler doesn't complain (the error occurs at runtime); it does complain, however, if I try a similar cast to an abstract class.
class Program
{
abstract class aBaz
{
public abstract int A { get; }
}
interface IBar
{
int B { get; }
}
class Foo
{
public int C { get; }
}
static void Main()
{
Foo foo = new Foo();
// compiler error, as expected, since Foo doesn't inherit aBaz
aBaz baz = (aBaz)foo;
// no compiler error, even though Foo doesn't implement IBar
IBar bar = (IBar)foo;
}
}
Why doesn't the compiler reject the cast from Foo to IBar, when it's (seemingly?) invalid? Or, to flip the question, if the compiler allows this "invalid" cast to the interface IBar, why doesn't it allow the similar "invalid" cast to the abstract class aBaz?
And to show that compiler is not stupid there is actulaly case when cast will fail at compile time: if compiler can prove that no other classes can derive from the class it will fail casting to interfaces at compile time:
In first case (
NoBar
) class is explicitly sealed (and hence no derived classes can implement IFoo) and compiler knows that it does not implementIBar
itself - hence can fail at compile time. Second case (NoBarValue
) is similar with only difference that value types (struct) are implicitly sealed.You need to understand the inheritance system of .Net to see why this makes sense. In .Net, a class may inherit from only one base class but may implement any number of interfaces.
In the extremely simple original example in the question, it seems like the compiler could detect that this instance of foo is never going to be castable to IBar, but that is more of a "nice to have" warning than a matter of language correctness.
The whole point of a cast is to suppress that compiler error.
(eg, if you know that
foo
is actually an instance of a subtype that does implement the interface)If the compiler can prove that it is impossible for the cast to succeed, it will still give an error. (eg, if you cast to a class that is not in its hierarchy)