closed (Referenční dokumentace jazyka C#)

Počínaje jazykem C# 15 můžete modifikátor použít closed u třídy a deklarovat uzavřenou hierarchii. Přímou podtyp lze odvodit pouze z uzavřené třídy v rámci deklarujícího sestavení. Vzhledem k tomu, že je sada přímých potomků pevná, výraz, switch který zpracovává jednotlivé přímé potomky, vyčerpá uzavřený základní typ a nepotřebuje výchozí arm.

// 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

Omezení stejného sestavení se vztahuje pouze na přímé potomky uzavřené třídy. Třída odvozená z uzavřené třídy není sama o sobě uzavřena, pokud ji closedtaké neoznačíte . Vzhledem k tomu, že Failed v předchozím příkladu je prostý záznam, může z něj odvozeno jiné sestavení:

// Assembly 2
public record class RetryableFailed(string Error, int Attempts) : Failed(Error); // OK: 'Failed' isn't sealed or closed

Pokud chcete zabránit odvození Failed také, deklarujte jej jako sealed nebo closed.

Referenční dokumentace jazyka C# dokumentuje naposledy vydané verze jazyka C#. Obsahuje také počáteční dokumentaci k funkcím ve verzi Public Preview pro nadcházející jazykovou verzi.

Dokumentace identifikuje všechny funkce, které byly poprvé představeny v posledních třech verzích jazyka nebo v aktuálních verzích Public Preview.

Tip

Informace o tom, kdy byla funkce poprvé představena v jazyce C#, najdete v článku o historii verzí jazyka C#.

Note

closed je kontextové klíčové slovo. Má zvláštní význam pouze tehdy, když se zobrazí jako modifikátor v deklaraci třídy. V jiných kontextech můžete dál používat closed jako identifikátor. Pokud potřebujete použít closed jako identifikátor v pozici, kde by modifikátor byl také platný, předpona ho @ předponou (například) informovat kompilátor, @closedaby s ním zachází jako s identifikátorem, a ne jako s modifikátorem.

Pravidla deklarace

closed Modifikátor je modifikátor třídy:

  • Třída closed je implicitně abstract. Nelze kombinovat closed s sealed, staticnebo explicitní abstract modifikátor.
  • Je nutné deklarovat přímý podtyp uzavřené třídy ve stejném sestavení a modulu jako uzavřená základní třída.
  • Třída odvozená z uzavřené třídy není sama o sobě uzavřená. closed Modifikátor znovu použijte, pokud chcete, aby byla také uzavřena odvozená třída.

Je-li obecná třída přímo odvozena od closed třídy, musí být každý parametr typu v odvozené třídě použit ve specifikaci základní třídy. Toto pravidlo není o samotném modifikátoru closed : uzavřený konstruovaný typ je obecný typ, jehož argumenty typu jsou plně zadané (například Tree<int>), na rozdíl od otevřeného typu jako Tree<T>. Pravidlo zajišťuje, že každý uzavřený vytvořený typ základní třídy má přesně jeden odpovídající uzavřený konstruovaný typ mezi jeho přímými potomky, takže kompilátor může zdůvodnět úplnost.

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

Vyčerpávající výrazy přepínače

switch Když výraz zpracovává všechny přímé potomky uzavřené třídy, kompilátor považuje přepínač za vyčerpávající a nevygeneruje upozornění na neúpatrnost:

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.
};

Pokud je výraz řízení přepínače null, stane se další možnou hodnotou, null kterou musí přepínač zpracovat. Přepnutí JobStatus? je vyčerpávající pouze v případech, kdy zahrnuje null:

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.
};

Pokud ho null vynecháte, kompilátor vás upozorní, že se vzor null nezpracuje. Stejné pravidlo platí, zda uzavřený typ je třída nebo struktura zvednuta na typ s možnou hodnotou null.

Další informace o tom, jak kompilátor určuje úplnost, včetně způsobu interakce uzavřených hierarchií s obecnými omezeními a přístupností, naleznete v tématu Uzavřené vzory hierarchie.

Parametry typu omezené na uzavřený typ

Parametr typu omezený na uzavřenou třídu je považován za uzavřenou třídu pro kontroly úplnosti. Výraz switch , jehož řídicí hodnota má takový parametr typu, je vyčerpávající, když zpracovává všechny přímé potomky uzavřeného omezení:

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 its direct descendants exhaust the switch.
};

Toto pravidlo se vztahuje na to, zda se parametr typu zobrazí v metodě nebo v obsahujícím typu.

specifikace jazyka C#

Další informace najdete ve specifikaci funkcí uzavřených hierarchií .

Viz také