interface (C#-Referenz)
Eine Schnittstelle definiert einen Vertrag. Jede class
-, record
- oder struct
-Klasse, die diesen Vertrag implementiert, muss eine Implementierung der in der Schnittstelle definierten Member bereitstellen. Eine Schnittstelle kann eine Standardimplementierung für Member definieren. Sie kann auch static
-Member definieren, um eine einzelne Implementierung für allgemeine Funktionen bereitzustellen. Ab C# 11 kann eine Schnittstelle static abstract
- oder static virtual
-Member definieren, um zu deklarieren, dass ein implementierender Typ die deklarierten Member bereitstellen muss. Typischerweise deklarieren static virtual
-Methoden, dass eine Implementierung eine Reihe überladener Operatoren festlegen muss.
Im folgenden Beispiel muss die Klasse ImplementationClass
eine Methode mit dem Namen SampleMethod
implementieren, die keine Parameter hat und void
zurückgibt.
Weitere Informationen und Beispiele finden Sie unter Schnittstellen.
Eine Schnittstelle der obersten Ebene, die in einem Namespace deklariert, aber nicht in einem anderen Typ geschachtelt ist, kann als public
oder internal
deklariert werden. Der Standardwert ist internal
. Geschachtelte Schnittstellendeklarationen, die innerhalb eines anderen Typs deklariert werden, können mit jedem Zugriffsmodifizierer deklariert werden.
Schnittstellenmitglieder ohne Implementierung können keinen Zugriffsmodifizierer enthalten. Mitglieder mit einer Standardimplementierung können jeden Zugriffsmodifizierer enthalten.
Beispielschnittstelle
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();
}
}
Eine Schnittstelle kann ein Member eines Namespaces oder einer Klasse sein. Eine Schnittstellendeklaration kann Deklarationen der folgenden Member enthalten (Signaturen ohne Implementierungen):
Standardschnittstellenmember
Diese vorstehenden Memberdeklarationen enthalten in der Regel keinen Körper. Ein Schnittstellenmember kann einen Körper deklarieren. Memberkörper in einer Schnittstelle sind die Standardimplementierung. Member mit Text ermöglichen der Schnittstelle, eine „Standardimplementierung“ für Klassen und Strukturen bereitzustellen, die keine überschreibende Implementierung bereitstellen.
Wichtig
Durch das Hinzufügen von Standardschnittstellenmitgliedern wird jede ref struct
, die die Schnittstelle implementiert, gezwungen, eine explizite Deklaration dieses Mitglieds hinzuzufügen.
Eine Schnittstelle kann Folgendes umfassen:
- Konstanten
- Operatoren
- Statischer Konstruktor
- Geschachtelte Typen
- Statische Felder, Methoden, Eigenschaften, Indexer und Ereignisse
- Memberdeklarationen, die die Syntax der explizite Schnittstellenimplementierung verwenden
- Explizite Zugriffsmodifizierer (der Standardzugriff ist
public
)
Statische abstrakte und virtuelle Member
Ab C# 11 kann eine Schnittstelle static abstract
- und static virtual
-Member für alle Membertypen außer für Felder deklarieren. Schnittstellen können deklarieren, dass implementierende Typen Operatoren oder andere statische Member definieren müssen. Mit diesem Feature können generische Algorithmen ein zahlenähnliches Verhalten angeben. Beispiele finden Sie in den numerischen Typen in der .NET-Runtime, z. B. System.Numerics.INumber<TSelf>. Diese Schnittstellen definieren allgemeine mathematische Operatoren, die von vielen numerischen Typen implementiert werden. Der Compiler muss Aufrufe von static virtual
- und static abstract
-Methoden zur Kompilierzeit auflösen. Die static virtual
- und static abstract
-Methoden, die in Schnittstellen deklariert werden, verfügen nicht über einen Dispatchmechanismus zur Laufzeit, der den in Klassen deklarierten virtual
- oder abstract
-Methoden entspricht. Stattdessen verwendet der Compiler Typinformationen, die zur Kompilierzeit verfügbar sind. static virtual
Daher werden Methoden fast ausschließlich in generischen Schnittstellen deklariert. Darüber hinaus deklarieren die meisten Schnittstellen, die static virtual
- oder static abstract
-Methoden deklarieren, dass einer der Typparameter die deklarierte Schnittstelle implementieren muss. Die Schnittstelle INumber<T>
deklariert beispielsweise, dass INumber<T>
von T
implementiert werden muss. Der Compiler verwendet das Typargument, um Aufrufe der in der Schnittstellendeklaration deklarierten Methoden und Operatoren aufzulösen. Der Typ int
implementiert z. B. INumber<int>
. Wenn der Typparameter T
das Typargument int
angibt, werden die für int
deklarierten static
-Member aufgerufen. Wenn double
das Typargument ist, werden alternativ die static
-Member aufgerufen, die für den Typ double
deklariert sind.
Wichtig
Dispatch von Methoden für static abstract
- und static virtual
-Methoden, die in Schnittstellen deklariert sind, wird über den Kompilierzeittyp eines Ausdrucks aufgelöst. Wenn der Laufzeittyp eines Ausdrucks von einem anderen Kompilierzeittyp abgeleitet ist, werden die statischen Methoden des Basistyps (Kompilierzeit) aufgerufen.
Sie können dieses Feature ausprobieren, indem Sie das Tutorial zu statischen abstrakten Membern in Schnittstellen durcharbeiten.
Schnittstellenvererbung
Schnittstellen dürfen keinen Instanzstatus enthalten. Obwohl statische Felder jetzt zulässig sind, sind Instanzfelder in Schnittstellen nicht zulässig. Automatische Eigenschaften von Instanzen werden in Schnittstellen nicht unterstützt, da sie implizit ein ausgeblendetes Feld deklarieren würden. Diese Regel hat eine fast unmerkliche Auswirkung auf Eigenschaftsdeklarationen. In einer Schnittstellendeklaration deklariert der folgende Code keine automatisch implementierte Eigenschaft wie in einem class
oder struct
. Stattdessen wird eine Eigenschaft deklariert, die keine Standardimplementierung hat, sondern in jedem Typ implementiert werden muss, der die Schnittstelle implementiert:
public interface INamed
{
public string Name {get; set;}
}
Eine Schnittstelle kann von einer oder mehreren Basisschnittstellen erben. Wenn eine Schnittstelle von einer anderen Schnittstelle erbt, muss ein Typ, der die abgeleitete Schnittstelle implementiert, alle Mitglieder implementieren, die sich in den Basisschnittstellen befinden und die in der abgeleiteten Schnittstelle deklariert werden, wie im folgenden Code gezeigt:
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() { }
}
Wenn eine Schnittstelle eine Methode überschreibt die in einer Basisschnittstelle implementiert ist, muss sie die Syntax der expliziten Schnittstellenimplementierung verwenden.
Wenn eine Basistypliste sowohl eine Basisklasse als auch Schnittstellen umfasst, muss die Basisklasse zuerst in der Liste stehen.
Eine Klasse, die eine Schnittstelle implementiert, kann Member dieser Schnittstelle explizit implementieren. Auf einen explizit implementierten Member kann nicht durch eine Klasseninstanz zugegriffen werden, sondern nur durch eine Instanz der Schnittstelle. Außerdem kann auf Standardschnittstellenmember nur über eine Instanz der Schnittstelle zugegriffen werden.
Weitere Informationen zur expliziten Implementierung finden Sie unter Explizite Schnittstellenimplementierung.
Beispielschnittstellenimplementierungen
Das folgende Beispiel veranschaulicht die Schnittstellenimplementierung. In diesem Beispiel enthält die Schnittstelle die Eigenschaftendeklaration, und die Klasse enthält die Implementierung. Eine beliebige Instanz einer Klasse, die IPoint
implementiert, hat die ganzzahligen Eigenschaften x
und 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#-Sprachspezifikation
Weitere Informationen finden Sie im Abschnitt Schnittstellen der C#-Sprachspezifikation, in der Featurespezifikation für C# 8: standardmäßige Schnittstellenmember und in der Featurespezifikation für C# 11: statische abstrakte Member in Schnittstellen.