When defining a C# interface, we can specify a default implementation. We can normally still implement the method in our class to replace it, but why does that not work after a base class is introduced in-between? There are several things going on here, which I don’t understand and did not expect, so I hope someone can explain what exactly is happening here.
Here’s an example – both assertions succeed, so depending on the static type, different methods are called.
private interface IFunny
{
void TryToCallMe() { }
}
private class BaseFunny : IFunny;
private class DerivedFunny : BaseFunny
{
public void TryToCallMe() => throw new InvalidOperationException();
}
[Fact]
public void FunStuff()
{
((Action)(() => new DerivedFunny().TryToCallMe())).Should().Throw<InvalidOperationException>();
((Action)(() => ((IFunny)new DerivedFunny()).TryToCallMe())).Should().NotThrow<InvalidOperationException>();
}
And a follow-up question: When I change the DerivedFunny
declaration like this,
public void IFunny.TryToCallMe() => throw new InvalidOperationException();
the compiler gives an error actually claiming that DerivedFunny
does not implement the interface IFunny
(which I think it should, as its base class does so).
Finally, I can redefine it like this:
private class DerivedFunny : BaseFunny, IFunny
{
public void TryToCallMe() => throw new InvalidOperationException();
}
which seems kind of redundant (unless that compiler error is true). With that implementation, the second assertion will now actually fail and the exception be thrown as well. That’s the behaviour I initially would have expected (aka this makes it “work for me”), but I would still prefer to understand why.