Why are C# interface methods not declared abstract or virtual?

C# methods in interfaces are declared without using the virtual keyword, and overridden in the derived class without using the override keyword.

Is there a reason for this? I assume that it is just a language convenience, and obviously the CLR knows how to handle this under the covers (methods are not virtual by default), but are there other technical reasons?

Here is the IL that a derived class generates:

class Example : IDisposable {
    public void Dispose() { }
}

.method public hidebysig newslot virtual final 
        instance void  Dispose() cil managed
{
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
} // end of method Example::Dispose

Notice that the method is declared virtual final in the IL.

106
задан Kara 8 July 2013 в 22:00
поделиться

3 ответа

В большинстве других сред скомпилированного кода интерфейсы реализованы в виде виртуальных таблиц — списка указателей на тела методов. Обычно класс, который реализует несколько интерфейсов, будет иметь где-то в своем внутреннем компиляторе сгенерированные метаданные список виртуальных таблиц интерфейса, по одной виртуальной таблице на каждый интерфейс (чтобы порядок методов сохранялся). Так же обычно реализуются COM-интерфейсы.

Однако в .NET интерфейсы не реализованы как отдельные виртуальные таблицы для каждого класса. Методы интерфейса индексируются через глобальную таблицу методов интерфейса, частью которой являются все интерфейсы. Следовательно, нет необходимости объявлять метод виртуальным, чтобы этот метод реализовывал интерфейсный метод — глобальная таблица методов интерфейса может просто указывать непосредственно на кодовый адрес метода класса.

Объявление метода виртуальным для реализации интерфейса не требуется и в других языках, даже на платформах, отличных от CLR. Одним из примеров является язык Delphi для Win32.

4
ответ дан 24 November 2019 в 03:49
поделиться

Цитирование Джеффри Ритчера из CLR через CSharp 3rd Edition здесь

Для CLR требуется этот интерфейс методы должны быть помечены как виртуальные. если ты не отмечайте метод явно как виртуальный в вашем исходном коде, компилятор помечает метод как виртуальный и запечатанный; это предотвращает производное класс от переопределения интерфейса метод. Если вы явно отметите метод как виртуальный, компилятор помечает метод как виртуальный (и оставляет его незапечатанный); это позволяет производному классу чтобы переопределить метод интерфейса. Если метод интерфейса запечатан, производный класс не может переопределить метод. Однако производный класс может повторно наследовать тот же интерфейс и может предоставить собственную реализацию для методы интерфейса.

73
ответ дан 24 November 2019 в 03:49
поделиться

Они не виртуальные (с точки зрения того, как мы о них думаем, если не с точки зрения базовой реализации, такой как (запечатанные виртуальные) — полезно прочитать другие ответы здесь и узнать что-то самому :-)

Они не ничего не переопределять - в интерфейсе нет реализации.

Все, что делает интерфейс, — это предоставляет «контракт», которого должен придерживаться класс — шаблон, если хотите, чтобы вызывающие знали, как вызывать объект, даже если они никогда раньше не видели этот конкретный класс.

Затем класс должен реализовать интерфейсный метод так, как он будет, в рамках контракта — виртуальный или «невиртуальный» (как оказалось, запечатанный виртуальный).

0
ответ дан 24 November 2019 в 03:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: