why virtual is allowed while implementing the interface methods?

34,700

Solution 1

Methods that are implemented from an interface are not virtual by default. You are merely providing an implementation of the contract defined in the interface definition. By marking the method as virtual, you are allowing derived classes to provide additional or separate implementation while still honoring the contract as defined.

Consider this example:

interface IAnimal
{
    string Speak();
}

class Dog : IAnimal
{
    public string Speak()
    {
        return "Bark!";
    }
}

The Dog class is implementing the interface by providing an implementation of the contract IAnimal. There are no virtual methods here and no overriding.

Now consider this example:

interface IAnimal
{
    string Speak();
}

class Dog : IAnimal
{
    public virtual string Speak()
    {
        return "Bark!";
    }
}

class GoldenRetriever : Dog
{
    public override string Speak()
    {
        return "I am a golden retriever who says " 
                   + base.Speak();
    }
}

Now the Dog class has declared Speak to be virtual which allows derived classes to provide an additional or new implementation. This does not break the contract with IAnimal as any call to the Speak method still returns a string.

Ok, one last example. Remember that interfaces don't require an implementation - they only require that the contract is satisfied. This means that the interface only cares that a member exists in the implementing class that has a matching signature. This means that we could also do this:

interface IAnimal
{
    string Speak();
}

abstract class Dog : IAnimal
{
    public abstract string Speak();
}

class GoldenRetriever : Dog
{
    public override string Speak()
    {
        return "I am a golden retriever";
    }
}

Notice now that the Dog class provides no implementation at all for Speak yet has satisfied the requirements of the contract.

Interfaces are also inherited from class to class so in all the examples above both Dog and GoldenRetriever implement the IAnimal interface. Neither class hide the Speak method - both classes implement it.


Ok, I think your confusion may be coming from the fact that the virtual method is defined in an interface, not a class. Here is the IL for the interface I defined above:

.class private interface abstract auto ansi IAnimal
{
    .method public hidebysig newslot abstract 
        virtual instance string Speak() cil managed
    {
    }
}

While you are correct that the method is defined as virtual you also need to notice that the type here is designated as an interface. This is purely an implementation detail of the MSIL generated by Microsoft's C# compiler - another compiler could easily generate different code as long as semantically it provided the same result.

The important thing here is this: even though the method is declared as virtual in the interface that does not mean that it is the same thing as a virtual method declared in class.

Solution 2

Interface is not Base Class, so implementation methods are not overriden. Interface only declares the methods, Interface methods are not virtual by default, infact interfaces only declare the methods that are available on the class that implements that interface.

Declaration can not be virtual.

Implementation can or cannot be virtual that is completely dependent on the implementer's logic.

Solution 3

There is a mix-up of the term 'virtual' here, between IL and C#. They do not completely correspond. Virtual in the IL sense means "it's called indirect" via a VMT(virtual method table), that is about the same mechanism for class overriding and interface implementation. In the IL sense, an interface member must be marked virtual - there is no way around. But if you look in the implementation, it's marked as 'virtual final'. That is something you cannot achieve in C#. 'Final' means, it cannot be overriden. It does not become virtual in the meaning of C#, unless you declare it manually as 'virtual' or 'abstract' in C#.

The implicit interface implementation of C# (it doesn't exist in VB.NET or IL) is quiet powerful. It does attach the Method of the implementing class, that matches in Name-Parameters-ReturnValue (the Signature, or SigAndName in the IL wording). This includes using base class implementations for the methods.

public interface ITest
{
    double MethodC(double a, double b, double c, double d);
}

internal class BaseClass
{
    public double MethodC(double a, double b, double c, double d)
    {
        return a+b+c+d;
    }
}

internal class OtherClass : BaseClass , ITest 
{
}

This actually works fine. But C# is doing a Trick here, Cause you use the BaseClass.MethodC as an interface implementation, it's marked as final virtual in the BaseClass. Yes, the way how BaseClass is implemented, depends on how BaseClass is used. BaseClass.MethodC is modified, cause it's used to implement ITest.MethodC in a derived class. This even works over file and project boundaries, as long as the source code of BaseClass is in the same solution.

So the output of the compilation of a project, is not the same, if you compile it by itself, or in a big solution together with other products. This is quiet noticable.

If the source code of BaseClass is not available, if you just linked into a DLL, then C# will generate a Wrapper to use the BaseClass implementation. It will actually do this:

internal class OtherClass : BaseClass , ITest 
{
    double ITest.MethodC(double a, double b, double c, double d)
    {
        return base.MethodC(a, b, c, d)
    }
}

This is done in secret, but it's absolutely necessary to have a method marked as virtual in the IL sense.

Share:
34,700
Mohit Bhandari
Author by

Mohit Bhandari

Updated on July 05, 2022

Comments

  • Mohit Bhandari
    Mohit Bhandari almost 2 years

    I have one specific query with the interfaces. By default interface methods are abstract and virtual so if we implement that interface and gives definition in the class we actually override that method but when we mark the method as a virtual again in the implementing class why the complier is not considering that we are actually trying to hide the original interface virtual method.Like if we have a virtual method in the base class and derived class again marked the method as virtual in that case compiler gives the warning that you are hiding the base class method so use new if you are intentionally hiding the base class method.

    public interface ITestInterface
    {
     void virtualmethod(); // this method is by default virtual. 
    }
    
    public class TestInterface :ITestInterface
    {
     public virtual void virtualmethod()
     {
    // Now compiler should consider that i am actually hiding the interface virtual method.
     }
    }
    

    if you build the above code for interface and open in ILDASM you will see the code like this: .method public hidebysig newslot abstract virtual instance void virtualmethod() cil managed { }//end of method ITestInterface::virtualmethod