Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Интерфейс определяет контракт. Любой class, recordили struct который реализует этот контракт, должен предоставить реализацию элементов, определенных в интерфейсе.
Интерфейс может определить реализацию по умолчанию для члена. Он также может определять static члены для предоставления единой реализации для общих функциональных возможностей.
Интерфейс может определить или static abstract членыstatic virtual, чтобы объявить, что тип реализации должен предоставлять объявленные члены. Как правило, методы объявляют, static virtual что реализация должна определять набор перегруженных операторов.
Справочные документы по языку C# описывают последнюю выпущенную версию языка C#. Она также содержит начальную документацию по функциям в общедоступных предварительных версиях для предстоящего языкового выпуска.
Документация определяет любую функцию, впервые представленную в последних трех версиях языка или в текущих общедоступных предварительных версиях.
Подсказка
Чтобы узнать, когда функция впервые появилась в C#, ознакомьтесь со статьей об истории версий языка C#.
В следующем примере класс ImplementationClass должен реализовать метод с именем SampleMethod, не имеющий параметров и возвращающий значение void.
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
static void Main()
{
// Declare an interface instance.
ISampleInterface obj = new ImplementationClass();
// Call the member.
obj.SampleMethod();
}
}
Дополнительные сведения и примеры см. в разделе Интерфейсы.
Модификаторы доступа
Интерфейс может быть членом пространства имен или класса. Вы можете объявить интерфейс верхнего уровня, объявленный в пространстве имен, но не вложенный внутри другого типа, как public или internal. Значение по умолчанию — internal. Объявления вложенных интерфейсов, объявленные внутри другого типа, можно объявить с помощью модификатора доступа.
Члены интерфейса без реализации (абстрактные члены) неявно public и не могут иметь другие модификаторы доступа. Элементы интерфейса с реализацией по умолчанию по умолчанию, private если не указать модификатор доступа, но можно объявить любой модификатор доступа (public, илиinternalprivateprotected).
Члены интерфейса
Объявление интерфейса может содержать следующие элементы:
- Методы.
- Свойства.
- Индексаторы.
- События.
- Константы.
- Операторы.
- Статический конструктор.
- Вложенные типы.
- Статические поля, методы, свойства, индексаторы и события.
- Явные модификаторы доступа (доступ по умолчанию для абстрактных методов —
public).
Члены интерфейса по умолчанию
Объявления членов обычно не содержат текст. Однако элемент интерфейса может объявить текст. Органы-члены в интерфейсе — это реализация по умолчанию. Используя элементы с телами, интерфейс может предоставить реализацию по умолчанию для классов и структур, которые не предоставляют переопределяющую реализацию.
Внимание
При добавлении элементов интерфейсов по умолчанию любой ref struct , реализующий интерфейс, должен явно объявить этот элемент.
Статические абстрактные и виртуальные члены
Интерфейс может объявлять и static abstract члены static virtual для всех типов элементов, кроме полей. Объявляя эти члены, интерфейс может требовать, чтобы реализация типов определяет операторы или другие статические члены. Эта функция позволяет универсальным алгоритмам указывать поведение, подобное числу. Примеры можно увидеть в числовых типах во время выполнения .NET, например System.Numerics.INumber<TSelf>. Эти интерфейсы определяют общие математические операторы, реализованные многими числовыми типами. Компилятор должен разрешать вызовы static virtual и static abstract методы во время компиляции. Методы static virtual , static abstract объявленные в интерфейсах, не имеют механизма диспетчеризации среды выполнения, аналогичного virtual методам или abstract объявленным в классах. Вместо этого компилятор использует сведения о типе, доступные во время компиляции.
static virtual Поэтому методы почти исключительно объявляются в универсальных интерфейсах. Кроме того, большинство интерфейсов, объявляющих или методы, static virtual объявляют, что один из параметров типа должен static abstract. Например, интерфейс объявляет, INumber<T> что T должен реализовываться INumber<T>. Компилятор использует аргумент типа для разрешения вызовов методов и операторов, объявленных в объявлении интерфейса. Например, int тип реализует INumber<int>. Когда параметр T типа обозначает аргумент intтипа, вызываются члены, static объявленные в int ней. Кроме того, если double аргумент типа является аргументом типа, вызываются члены, static объявленные в типе double .
Внимание
Диспетчеризация static abstract методов и static virtual методов, объявленных в интерфейсах, разрешается с помощью типа времени компиляции выражения. Если тип среды выполнения выражения является производным от другого типа времени компиляции, вызываются статические методы базового типа (время компиляции).
Эту функцию можно попробовать, работая с руководством по статическим абстрактным членам в интерфейсах.
Наследование интерфейса
Интерфейсы не могут содержать состояние экземпляра. Хотя статические поля теперь разрешены, поля экземпляров не допускаются в интерфейсах.
Автоматические свойства экземпляра не поддерживаются в интерфейсах, так как они неявно объявляют скрытое поле. Это правило оказывает незначительное воздействие на объявления свойств. В объявлении интерфейса следующий код не объявляет автоматически реализованное свойство, как это делается в class или struct. Вместо этого он объявляет свойство, которое не имеет реализации по умолчанию, но должно быть реализовано в любом типе, реализующем интерфейс.
public interface INamed
{
public string Name {get; set;}
}
Интерфейс может наследовать от одного или нескольких базовых интерфейсов. Когда интерфейс наследует от другого интерфейса, тип, реализующий производный интерфейс, должен реализовать все члены в базовых интерфейсах в дополнение к этим элементам, объявленным в производном интерфейсе, как показано в следующем коде:
public interface I1
{
void M1();
}
public interface I2 : I1
{
void M2();
}
public class C : I2
{
// implements I1.M1
public void M1() { }
// implements I2.M2
public void M2() { }
}
Когда интерфейс переопределяет метод, реализованный в базовом интерфейсе, он должен использовать синтаксис явной реализации интерфейса.
Если список базовых типов содержит базовый класс и интерфейсы, базовый класс должен стоять первым в списке.
Класс, реализующий интерфейс, может явно реализовывать члены этого интерфейса. Явным образом реализованный член нельзя получить через экземпляр класса, но только через экземпляр интерфейса. Кроме того, обращение к членам интерфейса по умолчанию можно осуществлять только через экземпляр интерфейса.
Дополнительные сведения о явной реализации интерфейса см. в статье Явная реализация интерфейса.
Пример реализации интерфейса
В следующем примере показана реализация интерфейса. В этом примере интерфейс содержит объявление свойства, а класс содержит реализацию. Любой экземпляр класса, который реализует IPoint, имеет целочисленные свойства x и y.
interface IPoint
{
// Property signatures:
int X { get; set; }
int Y { get; set; }
double Distance { get; }
}
class Point : IPoint
{
// Constructor:
public Point(int x, int y)
{
X = x;
Y = y;
}
// Property implementation:
public int X { get; set; }
public int Y { get; set; }
// Property implementation
public double Distance =>
Math.Sqrt(X * X + Y * Y);
}
class MainClass
{
static void PrintPoint(IPoint p)
{
Console.WriteLine("x={0}, y={1}", p.X, p.Y);
}
static void Main()
{
IPoint p = new Point(2, 3);
Console.Write("My Point: ");
PrintPoint(p);
}
}
// Output: My Point: x=2, y=3
Спецификация языка C#
Дополнительные сведения см. в разделе "Интерфейсы " спецификации языка C# и спецификации компонентов для статических абстрактных элементов в интерфейсах.