In a comment for a previous post (Top 10 differences between Java and C#), John P. Wood wrote:
As a (primarily) Java developer, I’ve also noticed that C# handles abstract classes that implement interfaces differently. In Java, an abstract class can implement an interface, and not provide implementations of all of the interface’s methods. It is the responsibility of the first concrete class that has that abstract class as an ancestor to implement all of the methods in the interface.
C# on the other hand seems to require that the abstract class provide implementations for all of the methods on the interface. Even if that implementation is just a method signature.
Like these 3 posts (1 (bottom), 2, 3), I am struggling with why the Microsoft Team chose to do this.
Why ask the developer to write a little stub for the interface method, when the abstract class has no intention of implementing it at all?
I believe it's a natural artifact of virtual and non-virtual methods in C# (gotcha #2). In Java, methods are virtual by default (as far as I'm aware, Java doesn't support non-virtual methods).
However, C# (being derived from C++) does support non-virtual methods. When an abstract class implements an interface in C#, you are given the chance to describe the interface methods as abstract, virtual or non-virtual. Here's exactly what each options means...
Option 1: abstract
No attempt at an implementation is made in the abstract class. It's up to the first concrete class to provide an implementation. As a side note, defining a method as abstract implicitly defines it as virtual. If this weren't the case, you wouldn't be able to override it in the child class which defeats the purpose of an abstract method.
Option 2: virtual
An attempt was made in the abstract class to implement this method, but the child class has the option of overriding it and providing its own implementation.
Option 3: non-virtual
Again, an attempt was made at an implementation in the abstract class. However, the child class cannot override this method. If a child class defines a method with the same name, the method will not be associated with the interface implemented in the abstract class. The method associated with the interface is the non-virtual method defined by the abstract class.
Java can do options 1 and 2, but it lacks option 3.
Java could define the method as final to prevent it from being overriden, but this is slightly different than non-virtual. The final keyword is more along the lines of seal in C#. By allowing an option 3, C# provides finer control over how interfaces are inherited.
If C# went the route of Java and permitted abstract classes to put off interface method definitions, these methods would need to be virtual by default. However, this would be inconsistent with C# methods being non-virtual by default.
In a nutshell, the C# developer is forced in the abstract class to decide exactly which of the three options to assign to the interface method. Anyway, that's my best guess...
Comments 11
Thanks for the explanation. Pretty reasonable guess if you ask me.
Great job writing this article, this has to be very confusing to Java people who also have to write C# — at least it was for me when I first started implementing interfaces with abstract base classes.
At first it is rather strange but then again it might steer people to write basic implementation methods which make sure for example that the conditions on calling the method (argument not null, etc.) are met, and only then call some abstract (virtual) method named the same expect for an “Internal” prefix.
Perhaps more discussion on how aren’t Java’s final methods essentially (user-wise, not necessarily implementation wise) the same as non-virtual C# methods.
Yes those “seal” the method from being overridden in any child class but there’s also the possibility of marking classes or packages as sealed.
In C# I believe you can still provide a “new” method, even if the “previous” implementation has been marked as non-virtual. This is very confusing I think, as you need to have a full reference to the class implementing this method marked as “new” in order to use it.
An interface method is virtual by definition. In fact, all an interface is, is an abstract class with nothing but abstract methods and properties, which are also virtual by definition. (A bit over simplified, but not much.)
Therefore, IMO, you are correct to assume this is an oversite in the language implementation.
Even if the IL code needs the method stubbed out for some technical reason, the compiler should hide this fact from the programmer.
While you are correct that you might override the methods and make them abstract, this would be unusual and while it should be allowed, it does not explain the requirement to define it in the abstract class.
This is probably to make you decide at the abstract class if the method implementation can be made virtual (overridable) or you are providing an implementation of the interface method in the abstract class that can overridden at the child or sealed at the abstract class.
@Joonas: Thanks for the feedback!
@Dave: I think Shafqat put it best. Instead of having a default for making the method virtual like in Java, the developer is left to make the decision in C#. Maybe a default makes sense, but then the question of whether it should be virtual or non-virtual comes up. C# (like C++) methods are non-virtual by default. Why should there be an exception for interface methods in an abstract class?
Really great explanation, thanks!
Thanks very much. I’m new to C# (I’m primarily a Java dev) and I spent half an hour hour tweaking my interface, abstract class and concrete class until it compiled. Wanting to know why this craziness was required I was lucky enough to find your page through google.
Thank you for the explanation!
I think that the main difference is that in Java they are virtual and in c# they are non-virtual by default. In Java you must specify bu using the final keyword that this method may not be overridden (making it non-virtual like c#’s default or in the case that it was already overridden and you want it to no longer be overridden it acts like the sealed keyword in c#). In C# it is the opposite, you must specify that you allow it to be overridden thus you must to the same with interfaces in abstract classes.
The preference is personal, it depends what you are writing basically, if a framework it is annoying in C# as you always have to make them as overridable, if you are writing an end user app it is nice since you don’t want to have to tell it all methods are not to be overridden.. and the opposite is true for Java. Just my 2 cents…
Why not use final keyword in the abstract class or interface if you don’t want the child class to override it (That way it’s non-virtual right)?
@kant: In Java, the final keyword stops the child class from overriding the method. You’ll get a compiler error like “Cannot overload the final method.” In C#, a non-virtual method also stops the child class from overriding it. However, you can still define a method with the same signature in C# (no compiler error), but this isn’t overriding — it’s hiding (which behaves differently at run-time).
Pingback: Invoking Interface Method in Abstract Class Method