Явная реализация интерфейса не может быть виртуальной - PullRequest
12 голосов
/ 17 августа 2011

Кстати, я уже видел этот элемент подключения , но я не могу понять, в чем проблема с его поддержкой.

Скажем, у меня есть следующий код:

public interface IInterface
{
    void Method();
}

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

в чем проблема с виртуальным идентификатором?Наличие виртуального модификатора позволило бы override указать, что в базовом классе есть другая реализация.Теперь я могу заставить его работать, удалив виртуальный метод и создав производный класс следующим образом:

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

однако таким образом у меня действительно нет никаких признаков того, что я что-то переопределяю.

Обновление:
В соответствии со спецификацией C # (часть: 20.4.1 Явные реализации элементов интерфейса) есть две причины.

  1. Сокрытие определенных методов (для которых я использую это).
  2. Наличие 2 функций с одинаковой сигнатурой, но с разными типами возврата (полезно, например, для IClonable).

Однако ничего не сказано о том, почему вы не можете создать эти методыВиртуальный.

Обновление 2:
Учитывая ответы, я думаю, что я должен перефразировать реальный вопрос здесь.Если вышеуказанные 2 причины являются причиной, по которой явная реализация интерфейсов стала возможной в первую очередь.Почему это будет проблемой, если вы сделаете метод виртуальным.

Ответы [ 5 ]

14 голосов
/ 17 августа 2011

Метод, реализующий интерфейс в явном виде, имеет специальную область видимости = вы не можете получить к нему доступ из другого метода, если не приведете "this" к целевому типу интерфейса.Я предполагаю, что это было причиной того, что виртуальный спецификатор не поддерживается - вы не можете переопределить метод, который не является частью обычного объектного интерфейса (private / protected / public).

Это мой обходной путь:

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

   }

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


 public class Derived : Base
 {
     protected override void Method()
     {
     }
 }
7 голосов
/ 17 августа 2011

однако таким образом у меня действительно нет никаких признаков того, что я что-то переопределяю

Ну, вы вроде как ... у вас есть факт, что это явно явная реализация интерфейса. Это показывает, что он обеспечивает полиморфное поведение для вызова этого метода, который указан в интерфейсе ... почему имеет значение, реализует ли интерфейс базовый класс также ? Какая разница для вас, когда вы будете читать код?

Для меня главное преимущество override состоит в том, чтобы убедиться, что я действительно получил правильную подпись - что она соответствует тому, что я пытаюсь переопределить. Вы уже получили это преимущество с явной реализацией интерфейса, как если бы вы указали несуществующий метод или неверные параметры и т. Д., Компилятор уже будет жаловаться.

Я могу отсортировать , чтобы увидеть вашу точку зрения, но я никогда не находил, что это является реальной проблемой.

0 голосов
/ 04 апреля 2013

Я думаю, что причина может быть просто показана в следующем примере.Рассмотрим следующий код:

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???
    }
}

Короче говоря, если вы явно реализуете несколько интерфейсов с одинаковой сигнатурой метода, ваши производные классы не будут знать, какой базовый метод вы хотите переопределить.

0 голосов
/ 14 сентября 2012

Возможность иметь явные реализации интерфейса виртуальными была бы полезна только в одном сценарии: когда переопределение производного класса должно вызывать реализацию родительского класса.К сожалению, даже если бы явные реализации интерфейса могли быть сделаны виртуальными, у переопределяющего класса не было бы способа вызвать реализацию своего родителя, если бы для этого не было нового синтаксиса.VB.net прекрасно справляется с этим, позволяя методу, реализующему интерфейс, быть объявленным Protected с именем, отличным от метода интерфейса.Таким образом, производный класс может переопределить метод Protected (используя соответствующее имя), и это переопределение может вызвать версию родительского класса (с тем же именем).

0 голосов
/ 17 августа 2011

Если существует только один интерфейс, который наследуется, зачем вам нужно:

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

Почему бы просто не перейти:

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