Why are C# interface methods not declared abstract or virtual?
For the interface, the addition of the abstract
, or even the public
keywords would be redundant, so you omit them:
interface MyInterface {
void Method();
}
In the CIL, the method is marked virtual
and abstract
.
(Note that Java allows interface members to be declared public abstract
).
For the implementing class, there are some options:
Non-overridable: In C# the class doesn't declare the method as virtual
. That means that it cannot be overridden in a derived class (only hidden). In the CIL the method is still virtual (but sealed) because it must support polymorphism regarding the interface type.
class MyClass : MyInterface {
public void Method() {}
}
Overridable: Both in C# and in the CIL the method is virtual
. It participates in polymorphic dispatch and it can be overridden.
class MyClass : MyInterface {
public virtual void Method() {}
}
Explicit: This is a way for a class to implement an interface but not provide the interface methods in the public interface of the class itself. In the CIL the method will be private
(!) but it will still be callable from outside the class from a reference to the corresponding interface type. Explicit implementations are also non-overridable. This is possible because there's a CIL directive (.override
) that will link the private method to the corresponding interface method that it's implementing.
[C#]
class MyClass : MyInterface {
void MyInterface.Method() {}
}
[CIL]
.method private hidebysig newslot virtual final instance void MyInterface.Method() cil managed
{
.override MyInterface::Method
}
In VB.NET, you can even alias the interface method name in the implementing class.
[VB.NET]
Public Class MyClass
Implements MyInterface
Public Sub AliasedMethod() Implements MyInterface.Method
End Sub
End Class
[CIL]
.method public newslot virtual final instance void AliasedMethod() cil managed
{
.override MyInterface::Method
}
Now, consider this weird case:
interface MyInterface {
void Method();
}
class Base {
public void Method();
}
class Derived : Base, MyInterface { }
If Base
and Derived
are declared in the same assembly, the compiler will make Base::Method
virtual and sealed (in the CIL), even though Base
doesn't implement the interface.
If Base
and Derived
are in different assemblies, when compiling the Derived
assembly, the compiler won't change the other assembly, so it will introduce a member in Derived
that will be an explicit implementation for MyInterface::Method
that will just delegate the call to Base::Method
.
So you see, every interface method implementation must support polymorphic behavior, and thus must be marked virtual on the CIL, even if the compiler must go through hoops to do it.
Comparison : interface methods vs virtual methods vs abstract methods
Virtual and abstract are almost the same. A virtual method has an implementation in the base class that can optionally be overridden, while an abstract method hasn't and must be overridden in a child class. Otherwise they are the same. Choosing between them depends on the situation. If you got a base implementation, you use virtual. If you don't, and you need every descendant to implement it for itself, you choose abstract.
Interface methods are implementations of a method that is declared in an interface that the class implements. This is quite unrelated to the other two. I think a method can be both virtual and interface. The advantage of interfaces is that you declare one interface (duh) that can be implemented by two totally different classes. That way, you can run the same code on two different classes, as long as the methods you'd like to call are declared in an interface they share.
Is an interface and an abstract class with just virtual abstract methods the same thing?
There are 2 main differences between Interfaces and abstract super-classes:
Abstract Classes
- code reuse is possible by using an abstract super-class
- you can only inherit one super-class
Interfaces
- every method has to be implemented in each sub-class
- a class can inherit more than 1 interface (multiple inheritance)
Reflection says that interface method are virtual in the implemented type, when they aren't?
All methods declared in an interface are marked as virtual abstract
, and all methods that implement interface methods in classes are marked as virtual final
, so the CLR knows it can't just call them directly - it has to do vtable lookups at runtime to call the right implementation. The interface implementations are still virtual, but you can't override them as they're final.
As an example, the following C# definition:
public interface IInterface {
void Method();
}
public class Class : IInterface {
public void Method() {}
}
compiles to the following IL:
.class public interface abstract IInterface {
.method public abstract virtual instance void Method() {}
}
.class public Class extends [mscorlib]System.Object implements IInterface {
.method public specialname rtspecialname instance void .ctor() {}
.method public virtual final instance void Method() {}
}
If a virtual method is declared abstract
It becomes clearer when you look at the code example directly above the quoted paragraph:
public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}
public abstract class E : D
{
public abstract override void DoWork(int i);
}
The virtual method D.DoWork
is inherited by E
, and, there, declared abstract. The method is still virtual, it has just become abstract as well.
As you correctly state, an abstract method is always virtual. If your friend is still unconvinced, here's an official quote for that:
An abstract method is implicitly a virtual method.
Why do abstract classes need to define abstract methods from interfaces they implement?
An abstract class is a fully-fledged type, just except it cannot be instantiated. Hence its full contract must be declared even though some of its methods are not implemented. A user of a particular abstract class must be able to bind to all its methods, be they coming from interfaces or directly declared in the abstract class. It the methods from interfaces were not (at least) declared (if not even implemented) in the abstract class, the used couldn't bind to them.
Further, classes and interfaces are somewhat loosely-coupled. A class may declare a method, which is later mapped to a same-signature method in an interface which is implemented by its descendant. Hence it is again a “good idea” from the language-design viewpoint to require all methods of interfaces being directly implemented on an abstract class to be actually declared in it.
You can think of an interface as a detachable feature (except when explicit implementations are used). The abstract class may live on its own and its direct users need not to know of any of its interfaces.
It's a design feature that only virtual methods can be left without an implementation, because the technical mechanism of virtual methods needs to be leveraged for the whole concept of abstract classes work in practice.
UPDATE: Example:
public interface IFoo { void M(); }
public abstract class Bar : IFoo
{
public virtual abstract void M();
public void N() { }
}
public class Baz : Bar
{
public override void M() { … }
}
…
public void Method(Bar par)
{
par.M();
}
…
Baz x = new Baz();
Method(x);
The Method
see the instance denoted by the variable x
as Bar
— neither as Baz
nor as IFoo
. In other words, the user of class Bar
does not care of whether it implemented one, two, ten, or no interface at all. All it does is access its members. It rely's on Bar
's contract, not of IFoo
s contract. Hence if Bar
implements IFoo
, it must define all members from IFoo
.
Explicit interface implementation cannot be virtual
however this way I've really no indication at all that I'm overriding something
Well, you do, sort of - you have the fact that it's clearly an explicit interface implementation. That shows it's providing polymorphic behaviour for that method call which is specified on an interface... why does it matter whether the base class also implemented the interface? What difference will it make to you when you read the code?
To me, the main benefit of stating override
is to make sure I've really got the right signature - that it matches the thing I'm trying to override. You've already got that benefit with explicit interface implementation, as if you give a non-existent method or the wrong parameters etc, the compiler will already complain.
I can sort of see your point, but I've never found it to be an actual problem.
Questions about Abstract method and interface method
Interface methods are abstract methods. Yes they are the same as abstract methods in abstract classes as both are abstract. A caveat here though is how they are handled when polymorphism comes into play. This can be illustrated with the following code:
interface IA
{
int xxx();
}
abstract class B
{
public abstract int yyy();
}
class C : B, IA
{
public int xxx()
{
return 1;
}
public int yyy()
{
return 1;
}
}
The yyy
definition actually hides the abstract method in B and needs to be declared as public override int yyy()...
to prevent this.
No. you cannot "partially implement the non-abstract methods in abstract class". You can partially implement an abstract class by providing some concrete methods and some abstract methods. You cannot "partially implement" an abstract method though. A method in an abstract class is either abstract or it isn't.
In your code example,
OrdinaryClass
is providing an implementation ofxxx
.OrdinaryClass2
is hiding that abstract method though and providing its ownxxx
. as mentioned in (1). Please read up on method hiding in C# for more details, eg http://www.akadia.com/services/dotnet_polymorphism.html and Overriding vs method hiding.
Related Topics
JSON.Net - Serialize Property Name Without Quotes
Repository Pattern Step by Step Explanation
How to Pass Anonymous Types as Parameters
Linq Order by Null Column Where Order Is Ascending and Nulls Should Be Last
Insert Data Using Entity Framework Model
Render Razor View to String in ASP.NET Core
Why Explicit Implementation of a Interface Can Not Be Public
The Entity Type Applicationuser Is Not Part of the Model for the Current Context
Callbackoncollecteddelegate in Globalkeyboardhook Was Detected
Why Does C# (4.0) Not Allow Co- and Contravariance in Generic Class Types
Nunit VS. Visual Studio 2008's Test Projects for Unit Testing
Non-Static Method Requires a Target
Converting a Generic List to a CSV String
How to Get the Current User Directory
Should You Declare Methods Using Overloads or Optional Parameters in C# 4.0
Get a Generic Method Without Using Getmethods
Mono Https Webrequest Fails with "The Authentication or Decryption Has Failed"