Для интерфейса добавление ключевых слов 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, даже если компилятор должен пройти через обручи, чтобы сделать это.