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?
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.
class Program
{
abstract class aBaz
{
public abstract int A { get; }
}
interface IBar
{
int B { get; }
}
class Foo
{
public int C { get; }
}
class BarableFoo : Foo, IBar
{
public int C { get; }
}
static void Main()
{
// This is why the compiler doesn't error on the later cast
Foo foo = new BarableFoo();
// compiler error: aBaz is a class and the compiler knows that
// Foo is not a _subclass_ of aBaz.
aBaz baz = (aBaz)foo;
// no compiler error: the class Foo does not implement IBar, however at runtime
// this instance, "foo", might be a subclass of Foo that _implements_ IBar.
// This is perfectly valid, and succeeds at runtime.
IBar bar = (IBar)foo;
// On the other hand...
foo = new Foo();
// This fails at runtime as expected.
bar = (IBar)foo;
}
}
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With