Для интерфейса добавление ключевых слов abstractили даже publicключевых слов было бы избыточным, поэтому вы их опускаете:
interface MyInterface {
void Method();
}
В CIL метод отмечен значком virtualи abstract.
(Обратите внимание, что Java позволяет объявлять элементы интерфейса public abstract).
Для класса реализации есть несколько вариантов:
Не допускает переопределения : в C # класс не объявляет метод как virtual. Это означает, что его нельзя переопределить в производном классе (только скрыть). В CIL метод по-прежнему виртуальный (но запечатанный), потому что он должен поддерживать полиморфизм относительно типа интерфейса.
class MyClass : MyInterface {
public void Method() {}
}
Переопределяемый : как в C #, так и в CIL используется метод virtual. Он участвует в полиморфной отправке и может быть отменен.
class MyClass : MyInterface {
public virtual void Method() {}
}
Явный : это способ для класса реализовать интерфейс, но не предоставлять методы интерфейса в общедоступном интерфейсе самого класса. В CIL метод будет private(!), Но он по-прежнему может быть вызван извне класса из ссылки на соответствующий тип интерфейса. Явные реализации также нельзя переопределить. Это возможно, потому что существует директива CIL ( .override), которая свяжет частный метод с соответствующим методом интерфейса, который он реализует.
[C #]
class MyClass : MyInterface {
void MyInterface.Method() {}
}
[CIL]
.method private hidebysig newslot virtual final instance void MyInterface.Method() cil managed
{
.override MyInterface::Method
}
В VB.NET вы даже можете указать псевдоним имени метода интерфейса в классе реализации.
[VB.NET]
Public Class MyClass
Implements MyInterface
Public Sub AliasedMethod() Implements MyInterface.Method
End Sub
End Class
[CIL]
.method public newslot virtual final instance void AliasedMethod() cil managed
{
.override MyInterface::Method
}
Теперь рассмотрим этот странный случай:
interface MyInterface {
void Method();
}
class Base {
public void Method();
}
class Derived : Base, MyInterface { }
Если Baseи Derivedобъявлены в одной сборке, компилятор сделает Base::Methodвиртуальный и запечатанный (в CIL), даже еслиBase не реализует интерфейс.
Если Baseи Derivedнаходятся в разных сборках, при компиляции Derivedсборки компилятор не изменит другую сборку, поэтому он представит член, в Derivedкотором будет явная реализация, поскольку MyInterface::Methodон просто делегирует вызов Base::Method.
Итак, вы видите, каждая реализация метода интерфейса должна поддерживать полиморфное поведение и, следовательно, должна быть помечена как виртуальная в CIL, даже если компилятор должен пройти через обручи, чтобы сделать это.