Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Interfejs definiuje kontrakt. Każdy classelement , recordlub struct implementujący ten kontrakt musi zapewnić implementację elementów członkowskich zdefiniowanych w interfejsie.
Interfejs może definiować domyślną implementację elementu członkowskiego. Może również definiować static elementy członkowskie w celu zapewnienia jednej implementacji dla typowych funkcji.
Interfejs może definiować static abstract elementy członkowskie lub static virtual zadeklarować, że typ implementujący musi podać zadeklarowane elementy członkowskie. Zazwyczaj metody deklarują, static virtual że implementacja musi definiować zestaw przeciążonych operatorów.
Dokumentacja języka C# zawiera ostatnio wydaną wersję języka C#. Zawiera również początkową dokumentację dla funkcjonalności w publicznych wersjach testowych nadchodzącego wydania języka.
Dokumentacja identyfikuje dowolną funkcję po raz pierwszy wprowadzoną w ostatnich trzech wersjach języka lub w bieżącej publicznej wersji zapoznawczej.
Wskazówka
Aby dowiedzieć się, kiedy funkcja została po raz pierwszy wprowadzona w języku C#, zapoznaj się z artykułem dotyczącym historii wersji języka C#.
W poniższym przykładzie klasa ImplementationClass musi zaimplementować metodę o nazwie SampleMethod , która nie ma parametrów i zwraca wartość 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();
}
}
Aby uzyskać więcej informacji i przykładów, zobacz Interfejsy.
Modyfikatory dostępu
Interfejs może być elementem członkowskim przestrzeni nazw lub klasy. Interfejs najwyższego poziomu można zadeklarować w przestrzeni nazw, ale nie zagnieżdżony wewnątrz innego typu, jako public lub internal. Wartość domyślna to internal. Deklaracje zagnieżdżonego interfejsu można zadeklarować wewnątrz innego typu przy użyciu dowolnego modyfikatora dostępu.
Elementy członkowskie interfejsu bez implementacji (abstrakcyjne elementy członkowskie) są niejawnie public i nie mogą mieć żadnego innego modyfikatora dostępu. Elementy członkowskie interfejsu z domyślną implementacją są private domyślnie, jeśli nie określisz modyfikatora dostępu, ale można zadeklarować dowolny modyfikator dostępu (public, private, protectedlub internal).
Składniki interfejsu
Deklaracja interfejsu może zawierać następujące elementy członkowskie:
- Metody.
- Właściwości.
- Indeksatory.
- Zdarzenia.
- Stałe.
- Operatory.
- Konstruktor statyczny.
- Typy zagnieżdżone.
- Pola statyczne, metody, właściwości, indeksatory i zdarzenia.
- Modyfikatory dostępu jawnego (domyślny dostęp dla metod abstrakcyjnych to
public).
Domyślne elementy członkowskie interfejsu
Deklaracje składowe zwykle nie zawierają treści. Jednak element członkowski interfejsu może zadeklarować treść. Elementy członkowskie w interfejsie są domyślną implementacją. Za pomocą elementów członkowskich z ciałami interfejs może zapewnić domyślną implementację klas i struktur, które nie zapewniają zastępowania implementacji.
Ważne
Jeśli dodasz domyślne elementy członkowskie interfejsów, które ref struct implementują interfejs, muszą jawnie zadeklarować ten element członkowski.
Statyczne abstrakcyjne i wirtualne elementy członkowskie
Interfejs może deklarować static abstract i static virtual składowe dla wszystkich typów elementów członkowskich z wyjątkiem pól. Deklarując te elementy członkowskie, interfejs może wymagać, aby implementowanie typów definiowało operatory lub inne statyczne elementy członkowskie. Ta funkcja umożliwia ogólne algorytmy określania zachowania przypominającego liczbę. Przykłady można zobaczyć w typach liczbowych w środowisku uruchomieniowym platformy .NET, takich jak System.Numerics.INumber<TSelf>. Te interfejsy definiują typowe operatory matematyczne implementowane przez wiele typów liczbowych. Kompilator musi rozpoznawać wywołania metod static virtual i w static abstract czasie kompilacji. Metody static virtual i static abstract zadeklarowane w interfejsach nie mają mechanizmu wysyłania środowiska uruchomieniowego analogicznego do virtual lub abstract metod zadeklarowanych w klasach. Zamiast tego kompilator używa informacji o typie dostępnych w czasie kompilacji. W związku z static virtual tym metody są prawie wyłącznie deklarowane w interfejsach ogólnych. Ponadto większość interfejsów, które deklarują metody lub deklarująstatic virtual, że jeden z parametrów typu musi implementować static abstract. Na przykład interfejs deklaruje, INumber<T> że T musi implementować INumber<T>element . Kompilator używa argumentu typu do rozpoznawania wywołań metod i operatorów zadeklarowanych w deklaracji interfejsu. Na przykład int typ implementuje INumber<int>wartość . Gdy parametr T typu oznacza argument inttypu , static wywoływane są elementy członkowskie zadeklarowane int na. Alternatywnie, gdy double jest argumentem typu, static elementy członkowskie zadeklarowane w typie double są wywoływane.
Ważne
Wysyłanie metody dla static abstract metod zadeklarowanych w interfejsach i static virtual jest rozwiązywane przy użyciu typu czasu kompilacji wyrażenia. Jeśli typ środowiska uruchomieniowego wyrażenia pochodzi z innego typu czasu kompilacji, wywoływane są metody statyczne w typie podstawowym (czas kompilacji).
Tę funkcję można wypróbować, pracując z samouczkiem dotyczącym statycznych abstrakcyjnych elementów członkowskich w interfejsach.
Dziedziczenie interfejsu
Interfejsy nie mogą zawierać stanu wystąpienia. Pola statyczne są teraz dozwolone, ale pola wystąpień nie są dozwolone w interfejsach.
Właściwości automatyczne wystąpienia nie są obsługiwane w interfejsach, ponieważ niejawnie deklarują ukryte pole. Ta reguła ma subtelny wpływ na deklaracje właściwości. W deklaracji interfejsu poniższy kod nie deklaruje automatycznie zaimplementowanej właściwości, tak jak w obiekcie class lub struct. Zamiast tego deklaruje właściwość, która nie ma implementacji domyślnej, ale musi być zaimplementowana w dowolnym typie, który implementuje interfejs:
public interface INamed
{
public string Name {get; set;}
}
Interfejs może dziedziczyć z co najmniej jednego interfejsu podstawowego. Gdy interfejs dziedziczy z innego interfejsu, typ implementowania interfejsu pochodnego musi implementować wszystkie elementy członkowskie w interfejsach podstawowych oprócz tych elementów członkowskich zadeklarowanych w interfejsie pochodnym, jak pokazano w poniższym kodzie:
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() { }
}
Gdy interfejs zastępuje metodę zaimplementowaną w interfejsie podstawowym, musi używać jawnej składni implementacji interfejsu.
Gdy lista typów podstawowych zawiera klasę bazową i interfejsy, klasa bazowa musi znajdować się na liście jako pierwsza.
Klasa, która implementuje interfejs, może jawnie implementować elementy członkowskie tego interfejsu. Jawnie zaimplementowany element członkowski nie może być dostępny za pośrednictwem wystąpienia klasy, ale tylko za pośrednictwem wystąpienia interfejsu. Ponadto dostęp do domyślnych elementów członkowskich interfejsu można uzyskać tylko za pośrednictwem wystąpienia interfejsu.
Aby uzyskać więcej informacji na temat jawnej implementacji interfejsu, zobacz Jawna implementacja interfejsu.
Przykładowa implementacja interfejsu
W poniższym przykładzie pokazano implementację interfejsu. W tym przykładzie interfejs zawiera deklarację właściwości, a klasa zawiera implementację. Każde wystąpienie klasy, która implementuje, ma właściwości IPoint liczb całkowitych x i 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
specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz sekcję Interfejsyspecyfikacji języka C# i specyfikację funkcji statycznych elementów abstrakcyjnych w interfejsach.