Reputation: 22340
New C# .NET Core Console App:
using System;
namespace Interface_Sealed
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new C().X);
Console.WriteLine((new C() as I).X);
Console.ReadKey();
}
interface I
{
sealed int X => 0;
}
class C: I
{
public int X => 1;
}
}
}
When run, this prints "10" to the console. The first ".X" is calling the implementation of X in the class C, and the second one is calling the default implementation on the interface I.
Why does C# allow me to declare the default implementation of X as "sealed", then allow me to override it with a different implementation without complaining? Why does it make a difference whether I access X through a reference of type I or of type C?
NB. If you implement I.X in C explicitly instead of implicitly, you get CS0539 "'Program.C.X' in explicit interface declaration is not found among members of the interface that can be implemented". The Microsoft documentation page for this error states that it occurs when "an attempt [is] made to explicitly declare an interface member that does not exist". Well, that's not true, is it? It does exist.
Upvotes: 2
Views: 199
Reputation: 203837
Why does C# allow me to declare the default implementation of X as "sealed", then allow me to override it with a different implementation without complaining?
It doesn't. You haven't overridden the member, merely made a new member with the same name. The fact that the member that returns 1
isn't called when the type is the interface type demonstrates this. This is entirely consistent with sealed members in classes inheriting from another. You aren't preventing a class implementing the interface from having it's own member with that name and signature, you're merely preventing it being the one that's associated with the interface (or base class).
Why does it make a difference whether I access X through a reference of type I or of type C?
Because both I
and C
have two different members that just coincidentally happen to have the same name and signature, but different behavior. They would only have the same behavior if you were able to override the interface's member, thereby changing the behavior of the member when called via the interface.
Well, that's not true, is it?
No, it is true. That member isn't a member that can be implemented because it's sealed. The member is there, but you can't change it's implementation, hence the error.
Upvotes: 4