Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Eine Schnittstelle enthält Definitionen für eine Gruppe von zugehörigen Funktionalitäten, die von einer nicht abstrakten class oder einer struct implementiert werden müssen. Eine Schnittstelle kann static Methoden definieren. Eine Schnittstelle kann eine Standardimplementierung für Member definieren. Eine Schnittstelle kann keine Instanzdaten wie Felder, automatisch implementierte Eigenschaften oder eigenschaftsähnliche Ereignisse deklarieren.
Durch die Verwendung von Schnittstellen können Sie beispielsweise das Verhalten aus mehreren Quellen in einer Klasse einbeziehen. Diese Funktion ist wichtig in C#, da die Sprache die mehrfache Vererbung von Klassen nicht unterstützt. Zudem müssen Sie eine Schnittstelle verwenden, wenn Sie die Vererbung für Strukturen simulieren möchten, da sie tatsächlich nicht von einer anderen Struktur oder Klasse erben können.
Sie definieren eine Schnittstelle durch die Verwendung des Schlüsselworts interface, wie im folgenden Beispiel gezeigt.
interface IEquatable<T>
{
bool Equals(T obj);
}
Der Name der Schnittstelle muss ein gültiger C#-Bezeichnername sein. Gemäß Konvention beginnen Schnittstellennamen mit dem Großbuchstaben I.
Jede die IEquatable<T>-Schnittstelle implementierende Klasse oder Struktur muss eine Definition für eine Equals-Methode enthalten, die mit der Signatur übereinstimmt, die durch die Schnittstelle angegeben wird. Daher können Sie davon ausgehen, dass eine Klasse vom Typ T, die IEquatable<T> implementiert, eine Methode Equals enthält, mit der eine Instanz dieser Klasse feststellen kann, ob sie mit einer anderen Instanz derselben Klasse identisch ist.
Die Definition von IEquatable<T> stellt keine Implementierung für Equals bereit. Eine Klasse oder Struktur kann mehrere Schnittstellen implementieren. Eine Klasse kann jedoch nur von einer einzelnen Klasse erben.
Weitere Informationen zu abstrakten Klassen finden Sie unter Abstrakte und versiegelte Klassen und Klassenmember.
Schnittstellen können Instanzmethoden, Eigenschaften, Ereignisse, Indexer oder eine beliebige Kombination aus diesen vier Membertypen enthalten. Schnittstellen können statische Konstruktoren, Felder, Konstanten oder Operatoren enthalten. Schnittstellenmitglieder, die keine Felder sind, können static abstract sein. Eine Schnittstelle kann keine Instanzfelder, Instanzkonstruktoren oder FInalizer enthalten. Schnittstellenmember sind standardmäßig öffentlich, und Sie können Zugriffsmodifizierer explizit angeben, z. B. public, protected, internal, private, protected internal oder private protected. Ein private-Member muss über eine Standardimplementierung verfügen.
Um ein Schnittstellenmitglied mithilfe der impliziten Implementierung zu implementieren, muss das entsprechende Mitglied der implementierenden Klasse öffentlich, nicht statisch sein und denselben Namen und dieselbe Signatur wie das Schnittstellenelement aufweisen. Sie müssen eine explizite Schnittstellenimplementierung verwenden, um Schnittstellenmitglieder zu implementieren, die nicht öffentlich sein sollen.
Hinweis
Wenn eine Schnittstelle statische Member deklariert, kann ein Typ, der diese Schnittstelle implementiert, auch statische Member mit derselben Signatur deklarieren. Diese Mitglieder werden durch den Typ, der das Mitglied deklariert, eindeutig identifiziert. Der in einem Typ deklarierte statische Member überschreibt nicht den in der Schnittstelle deklarierten statischen Member.
Eine Klasse oder Struktur, die eine Schnittstelle implementiert, muss eine Implementierung für alle deklarierten Member angeben, sofern keine Standardimplementierung durch die Schnittstelle bereitgestellt wird. Wenn jedoch eine Basisklasse eine Schnittstelle implementiert, erbt jede von der Basisklasse abgeleitete Klasse diese Implementierung.
Im folgenden Beispiel wird eine Implementierung der IEquatable<T>-Schnittstelle veranschaulicht. Die Implementierungsklasse Car muss die Implementierung der Equals-Methode bereitstellen.
public class Car : IEquatable<Car>
{
public string? Make { get; set; }
public string? Model { get; set; }
public string? Year { get; set; }
// Implementation of IEquatable<T> interface
public bool Equals(Car? car)
{
return (this.Make, this.Model, this.Year) ==
(car?.Make, car?.Model, car?.Year);
}
}
Eigenschaften und Indexer einer Klasse können zusätzliche Accessoren für eine Eigenschaft oder einen Indexer definieren, die in einer Schnittstelle deklariert sind. Beispielsweise kann eine Schnittstelle eine Eigenschaft deklarieren, die einen Get-Accessor aufweist. Die Klasse zur Implementierung der Schnittstelle kann dieselbe Eigenschaft mit einem get- und einem set-Accessor deklarieren. Wenn die Eigenschaft oder der Indexer jedoch die explizite Implementierung verwendet, müssen die Accessors übereinstimmen. Weitere Informationen zur expliziten Implementierung finden Sie unter Explizite Schnittstellenimplementierung und unter Schnittstelleneigenschaften.
Schnittstellen können von einer oder mehreren Schnittstellen erben. Die abgeleitete Schnittstelle erbt die Member von den Basisschnittstellen. Eine Klasse, die eine abgeleitete Schnittstelle implementiert, muss alle Member in der abgeleiteten Schnittstelle implementieren, einschließlich alle Member der Basisschnittstellen der abgeleiteten Schnittstelle. Diese Klasse kann implizit in die abgeleitete Schnittstelle oder eine seiner Basisschnittstellen konvertiert werden. Eine Klasse kann eine Schnittstelle mehrfach über geerbte Basisklassen einbeziehen, die sie erbt, oder über Schnittstellen, die von anderen Schnittstellen geerbt werden. Die Klasse kann jedoch nur einmal eine Implementierung einer Schnittstelle bereitstellen und auch nur dann, wenn die Klasse die Schnittstelle als Bestandteil der Definition der Klasse (class ClassName : InterfaceName) deklariert. Wenn die Schnittstelle geerbt wurde, da Sie eine Basisklasse geerbt haben, die die Schnittstelle implementiert, bietet die Basisklasse die Implementierung der Member der Schnittstelle. Die abgeleitete Klasse kann jedoch anstelle der Verwendung der geerbten Implementierung jegliche virtuellen Schnittstellenmember erneut implementieren. Wenn Schnittstellen eine Standardimplementierung einer Methode deklarieren, erbt jede Klasse, die diese Schnittstelle implementiert, diese Implementierung (Sie müssen die Klasseninstanz in den Schnittstellentyp umwandeln, um auf die Standardimplementierung des Schnittstellenmembers zuzugreifen).
Eine Basisklasse kann zudem Schnittstellenmember mithilfe von virtuellen Membern implementieren. In diesem Fall kann eine abgeleitete Klasse das Schnittstellenverhalten durch das Überschreiben der virtuellen Member ändern. Weitere Informationen über virtuelle Member finden Sie unter Polymorphie.
Arbeiten mit internen Schnittstellen
Eine interne Schnittstelle kann in der Regel durch eine implizite Implementierung mit öffentlichen Mitgliedern umgesetzt werden, solange alle Typen in der Schnittstellensignatur öffentlich zugänglich sind. Wenn eine Schnittstelle jedoch interne Typen in ihren Membersignaturen verwendet, wird die implizite Implementierung unmöglich, da das implementierende Klassenmitglied öffentlich sein muss, während interne Typen offengelegt werden. In solchen Fällen müssen Sie die explizite Schnittstellenimplementierung verwenden.
Das folgende Beispiel zeigt beide Szenarien:
// Internal type that cannot be exposed publicly
internal class InternalConfiguration
{
public string Setting { get; set; } = "";
}
// Internal interface that CAN be implemented with public members
// because it only uses public types in its signature
internal interface ILoggable
{
void Log(string message); // string is public, so this works with implicit implementation
}
// Interface with internal accessibility using internal types
internal interface IConfigurable
{
void Configure(InternalConfiguration config); // Internal type prevents implicit implementation
}
// This class shows both implicit and explicit interface implementation
public class ServiceImplementation : ILoggable, IConfigurable
{
// Implicit implementation works for ILoggable because string is public
public void Log(string message)
{
Console.WriteLine($"Log: {message}");
}
// Explicit implementation required for IConfigurable because it uses internal types
void IConfigurable.Configure(InternalConfiguration config)
{
// Implementation here
Console.WriteLine($"Configured with: {config.Setting}");
}
// If we tried implicit implementation for IConfigurable, this wouldn't compile:
// public void Configure(InternalConfiguration config) // Error: cannot expose internal type
}
Im vorherigen Beispiel verwendet die IConfigurable Schnittstelle einen internen Typ InternalConfiguration in der Methodensignatur. Die ServiceImplementation Klasse kann keine implizite Implementierung verwenden, da dies erforderlich wäre, um die Configure Methode öffentlich zu machen, was nicht zulässig ist, wenn die Methodensignatur interne Typen enthält. Stattdessen wird eine explizite Schnittstellenimplementierung verwendet, die keinen Zugriffsmodifizierer aufweist und nur über den Schnittstellentyp zugänglich ist.
Im Gegensatz dazu kann die ILoggable Schnittstelle implizit mit öffentlichen Mitgliedern umgesetzt werden, da alle Typen in ihrer Signatur (string) öffentlich zugänglich sind, auch wenn die Schnittstelle selbst intern ist.
Weitere Informationen zur expliziten Schnittstellenimplementierung finden Sie unter Explizite Schnittstellenimplementierung.
Zusammenfassung zu Schnittstellen
Eine Schnittstelle verfügt über die folgenden Eigenschaften:
- In C#-Versionen vor Version 8.0 ähnelt eine Schnittstelle einer abstrakten Basisklasse mit nur abstrakten Membern. Klasse oder Struktur, die die Schnittstelle implementiert, muss alle zugehörigen Member implementieren.
- Ab C# 8.0 kann eine Schnittstelle Standardimplementierungen für einige oder alle ihrer Mitglieder definieren. Eine Klasse oder eine Struktur, die die Schnittstelle implementiert, muss keine Member implementieren, die über Standardimplementierungen verfügen. Weitere Informationen finden Sie unter Standardschnittstellenmethoden.
- Eine Schnittstelle kann nicht direkt instanziiert werden.
- Eine Klasse oder Struktur kann mehrere Schnittstellen implementieren. Eine Klasse kann eine Basisklasse erben und zudem eine oder mehrere Schnittstellen implementieren.