Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Począwszy od języka C# 15, można zastosować closed modyfikator do klasy w celu zadeklarowania zamkniętej hierarchii. Bezpośredni podtyp można uzyskać tylko z zamkniętej klasy w ramach deklarowanego zestawu. Ponieważ zestaw elementów potomnych bezpośrednich jest stały, switch wyrażenie obsługujące każdy bezpośredni element potomny wyczerpuje zamknięty typ podstawowy i nie wymaga domyślnego ramienia.
// Assembly 1
public closed record class JobStatus;
public record class Queued : JobStatus;
public record class Running(int PercentComplete) : JobStatus;
public record class Completed(TimeSpan Elapsed) : JobStatus;
public record class Failed(string Error) : JobStatus;
// Assembly 2
public record class Paused : JobStatus; // Error: 'JobStatus' is a closed class
Ograniczenie tego samego zestawu dotyczy tylko bezpośrednich elementów potomnych klasy zamkniętej. Klasa pochodząca z zamkniętej klasy nie jest zamknięta, chyba że oznaczysz ją closedrównież jako . Ponieważ Failed w poprzednim przykładzie jest to zwykły rekord, inny zestaw może pochodzić z niego:
// Assembly 2
public record class RetryableFailed(string Error, int Attempts) : Failed(Error); // OK: 'Failed' isn't sealed or closed
Jeśli chcesz również uniemożliwić wyprowadzanie Failed , zadeklaruj go jako sealed lub closed.
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.
Tip
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#.
Note
closed jest kontekstowym słowem kluczowym. Ma specjalne znaczenie tylko wtedy, gdy pojawia się jako modyfikator w deklaracji klasy. Możesz nadal używać closed go jako identyfikatora w innych kontekstach. Jeśli musisz użyć closed jako identyfikatora w sytuacji, w której modyfikator będzie również prawidłowy, prefiks z @ (na przykład @closed), aby poinformować kompilator o traktowaniu go jako identyfikatora, a nie modyfikatora.
Reguły deklaracji
Modyfikator closed jest modyfikatorem klas:
- Klasa
closedjest niejawnieabstract. Nie można połączyć zclosedmodyfikatoremsealedjawnymstatic,abstractani jawnym. - Należy zadeklarować bezpośredni podtyp zamkniętej klasy w tym samym zestawie i module co zamknięta klasa bazowa.
- Klasa pochodząca z zamkniętej klasy nie jest zamknięta.
closedPonownie zastosuj modyfikator, jeśli chcesz również zamknąć klasę pochodną.
Jeśli klasa ogólna pochodzi bezpośrednio z closed klasy, każdy parametr typu w klasie pochodnej musi być używany w specyfikacji klasy bazowej.
Zamknięty skonstruowany typ jest typem ogólnym, którego argumenty typu są w pełni określone (na przykład ), w przeciwieństwie do typu otwartego, takiego jak Tree<T>Tree<int>. Typ otwarty może również zawierać określone argumenty typu, takie jak Dictionary<string, TValue>, gdzie TValue jest nadal parametrem typu. Aby zapoznać się z definicjami, zobacz Typy otwarte i zamknięte w specyfikacji języka. Ograniczenie pozwala kompilatorowi określić możliwe skonstruowane obiekty potomne dla danej konstrukcji bazowej. Konkretna konstrukcja bazowa nie może mieć odpowiedniej konstrukcji określonego potomka; reguła nie gwarantuje tej reguły.
public closed record class Tree<T>;
public record class Leaf<T>(T Value) : Tree<T>; // OK: 'T' appears in the base class
public record class Branch<T>(Tree<T> Left, Tree<T> Right) : Tree<T>; // OK: 'T' appears in the base class
public record class Constant<U>(U Value) : Tree<int> { } // Error: 'U' isn't used in the base class
Wyczerpujące wyrażenia przełącznika
switch Gdy wyrażenie obsługuje każdy bezpośredni element potomny zamkniętej klasy, kompilator uwzględnia przełącznik wyczerpujący i nie generuje ostrzeżenia o niewyczerpliwości:
public static string Describe(JobStatus status) => status switch
{
Queued => "waiting to start",
Running(var percent) => $"{percent}% complete",
Completed(var elapsed) => $"finished in {elapsed.TotalSeconds:F1}s",
Failed(var error) => $"failed: {error}",
// No warning: every direct descendant of 'JobStatus' is handled.
};
Gdy wyrażenie zarządzające przełącznikiem ma wartość null, null staje się kolejną możliwą wartością, którą przełącznik musi obsłużyć. Przełączenie JobStatus? jest wyczerpujące tylko wtedy, gdy obejmuje nullrównież :
public static string DescribeOrUnknown(JobStatus? status) => status switch
{
null => "unknown",
Queued => "waiting to start",
Running(var percent) => $"{percent}% complete",
Completed(var elapsed) => $"finished in {elapsed.TotalSeconds:F1}s",
Failed(var error) => $"failed: {error}",
// No warning: every direct descendant of 'JobStatus' is handled, and null is handled.
};
Jeśli pominięto null ramię, kompilator ostrzega, że wzorzec null nie jest obsługiwany. Modyfikator closed dotyczy tylko klas, w tym klas rekordów.
Aby uzyskać więcej informacji na temat sposobu określania wyczerpującości przez kompilator, w tym sposobu interakcji zamkniętych hierarchii z ogólnymi ograniczeniami i ułatwieniami dostępu, zobacz Zamknięte wzorce hierarchii.
Parametry typu ograniczone do typu zamkniętego
Specyfikacja funkcji zamkniętych hierarchii traktuje parametr typu ograniczony do zamkniętej klasy tak samo jak klasa zamknięta w celu sprawdzania wyczerpującości.
switch Wyrażenie, którego wartość rządząca ma taki parametr typu, jest wyczerpujące, gdy obsługuje każdy bezpośredni element potomny zamkniętego ograniczenia, niezależnie od tego, czy parametr typu pojawia się w metodzie, czy w typie zawierającym:
public static string DescribeJob<X>(X status) where X : JobStatus => status switch
{
Queued => "waiting to start",
Running(var percent) => $"{percent}% complete",
Completed(var elapsed) => $"finished in {elapsed.TotalSeconds:F1}s",
Failed(var error) => $"failed: {error}",
// No warning: 'X' is constrained to a closed type, so the compiler treats
// this switch as exhaustive because every direct descendant is handled.
};
specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz Specyfikację funkcji Zamknięte hierarchie .