Подтвердить что ты не робот

Явная реализация интерфейса не может быть виртуальной

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

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

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();
    }
}

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

Update:
Согласно С# (часть: 20.4.1 Явные реализации элементов интерфейса), есть две причины.

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

Ничего не говорится о том, почему вы не можете сделать эти методы виртуальными.

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Интерфейс реализации метода явно имеет специальную область видимости = вы не можете использовать его из другого метода, если только вы не нанесете "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()
     {
     }
 }

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

Введя защищенный виртуальный/абстрактный метод, вы можете заставить его работать:

public interface IInterfaceA
{
    void Method();
}

public interface IInterfaceB
{
    void Method();
}

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

    void IInterfaceB.Method()
    {
        MethodB();
    }

    protected virtual void MethodA()
    {
        Console.WriteLine("Called through base class interface A.");
    }

    protected virtual void MethodB()
    {
        Console.WriteLine("Called through base class interface B.");
    }
}

public class Derived : Base
{
    protected override void MethodB()
    {
        Console.WriteLine("Called through derived class interface B.");
    }
}

Ответ 6

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

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

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