Explicit interface implementation cannot be virtua

2019-03-15 07:31发布

问题:

For the record, I've already seen this connect item but I can't really understand what would be the problem in supporting this.

Say I have the following code:

public interface IInterface
{
    void Method();
}

public class Base : IInterface
{
    virtual void IInterface.Method()
    {
        throw new NotImplementedException();
    }
}

what is the problem with the virtual identifier? Having a virtual modifier would make it possible to override indicating there's a different implementation in the base class. I can make it work now by removing the virtual method and creating the derived class like this:

public class Derived : IInterface
{
    void IInterface.Method()
    {
        throw new NotImplementedException();
    }
}

however this way I've really no indication at all that I'm overriding something.

Update:
According to the C# (part: 20.4.1 Explicit interface member implementations) spec there are 2 reasons.

  1. Hiding of certain methods (which I'm using it for).
  2. Having 2 functions with the same signature but different return types (usefull for IClonable for example).

It doesn't say anything however about why you can't make these methods virtual.

Update2:
Given the answers I think I should rephrase the real question here. If The above 2 reasons are the reason why explicit implementation of interfaces was made possible in the first place. Why would it be a problem if you make a method virtual.

回答1:

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.



回答2:

A method implementating interface explicitly has a special visibility scope = you cannot acces it from another method unless you cast "this" to the target interface type. I suppose it was the reason why virtual specifier is not supported - you cannot override method that is not part of the normal object interface (private/protected/public).

This is my workaround:

public class Base : IInterface
{    
   protected virtual void Method()
   {

   }

   void IInterface.Method()    
   {        
       this.Method()
   }
 }


 public class Derived : Base
 {
     protected override void Method()
     {
     }
 }


回答3:

If there is only one interface that is being inherited from, why do you need to do:

public class Base : IInterface
{
    virtual void IInterface.Method()
    {
       throw new NotImplementedException();
    }
}

Why not just go:

public class Base : IInterface
{
   virtual void Method()
   {
      throw new NotImplementedException();
   }
}


回答4:

Being able to have explicit interface implementations be virtual would be useful in only one scenario: when a derived-class override needs to call the parent-class implementation. Unfortunately, even if explicit interface implementations could be made virtual, there wouldn't be any way for an overriding class to call its parent's implementation absent some new syntax for doing so. VB.net handles this nicely by allowing a method which implements an interface to be declared Protected with a different name from the interface's method. A derived class can thus override the Protected method (using the appropriate name), and that override can call the parent-class version (using the same name).



回答5:

I think the reason can be simply shown in following example. Consider this code:

public interface IInterfaceA
{
    void Method();
}

public interface IInterfaceB
{
    void Method();
}

public class Base : IInterfaceA, IInterfaceB
{
    virtual void IInterfaceA.Method()
    {
       ...
    }

    virtual void IInterfaceB.Method()
    {
       ...
    }
}

public class Derived : Base
{
    public override void Method()
    {
        // Will this override IInterfaceA or IInterfaceB implementation???
    }
}

So, in short, if you explicitly implement multiple interfaces with the same method signature your derived classes will not know which base method you want to override.