Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A partir do C# 15, você pode aplicar o closed modificador a uma classe para declarar uma hierarquia fechada. Você só pode derivar um subtipo direto de uma classe fechada dentro de seu assembly de declaração. Como o conjunto de descendentes diretos é fixo, uma switch expressão que manipula cada descendente direto esgota o tipo de base fechado e não precisa de um braço padrão.
// 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
A restrição do mesmo assembly aplica-se somente aos descendentes diretos da classe fechada. Uma classe derivada de uma classe fechada não é fechada, a menos que você também a marque closed. Como Failed no exemplo anterior há um registro sem formatação, outro assembly pode derivar dele:
// Assembly 2
public record class RetryableFailed(string Error, int Attempts) : Failed(Error); // OK: 'Failed' isn't sealed or closed
Se você quiser impedir a derivação também Failed , declare-a como sealed ou closed.
A linguagem C# faz referência a documentos da versão mais recentemente lançada da linguagem C#. Ele também contém a documentação inicial para funcionalidades em pré-visualizações públicas para o próximo lançamento do idioma.
A documentação identifica qualquer recurso introduzido pela primeira vez nas três últimas versões do idioma ou nas versões prévias públicas atuais.
Dica
Para descobrir quando um recurso foi introduzido pela primeira vez em C#, consulte o artigo sobre o histórico de versão da linguagem C#.
Note
closed é uma palavra-chave contextual. Ele só tem um significado especial quando aparece como um modificador em uma declaração de classe. Você pode continuar a usar closed como um identificador em outros contextos. Se você precisar usar closed como um identificador em uma posição em que o modificador também seria válido, prefixe-o com @ (por exemplo, @closed) para dizer ao compilador para tratá-lo como um identificador em vez do modificador.
Regras de declaração
O closed modificador é um modificador de classe:
- Uma
closedclasse é implicitamenteabstract. Você não pode combinarclosedcomsealed,staticou um modificador explícitoabstract. - Você deve declarar um subtipo direto de uma classe fechada no mesmo assembly e módulo da classe base fechada.
- Uma classe que deriva de uma classe fechada não está fechada. Aplique o
closedmodificador novamente se desejar que uma classe derivada também seja fechada.
Se uma classe genérica derivar diretamente de uma closed classe, cada parâmetro de tipo na classe derivada deverá ser usado na especificação de classe base. Essa regra não se trata do closed modificador em si: um tipo construído fechado é um tipo genérico cujos argumentos de tipo são totalmente especificados (como Tree<int>), em vez de um tipo aberto como Tree<T>. A regra garante que cada tipo construído fechado da classe base tenha exatamente um tipo construído fechado correspondente entre seus descendentes diretos, de modo que o compilador possa raciocinar sobre esgotamento.
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
Expressões de comutador exaustivas
Quando uma switch expressão manipula cada descendente direto de uma classe fechada, o compilador considera o comutador exaustivo e não gera um aviso de não esgotamento:
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.
};
Quando a expressão de controle de comutador é anulável, null torna-se outro valor possível que a opção deve manipular. Uma alternância JobStatus? é exaustiva somente quando também abrange 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.
};
Se você omitir o null braço, o compilador avisará que o padrão null não é tratado. A mesma regra se aplica se o tipo fechado é uma classe ou um struct elevado a um tipo anulável.
Para obter mais informações sobre como o compilador determina o esgotamento, incluindo como hierarquias fechadas interagem com restrições genéricas e acessibilidade, consulte padrões de hierarquia fechados.
Parâmetros de tipo restritos a um tipo fechado
Um parâmetro de tipo restrito a uma classe fechada é tratado como aquela classe fechada para verificações de esgotamento. Uma switch expressão cujo valor de controle tem esse parâmetro de tipo é exaustiva quando manipula cada descendente direto da restrição fechada:
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.
};
Essa regra se aplica se o parâmetro de tipo aparece em um método ou no tipo que contém.
Especificação da linguagem C#
Para obter mais informações, consulte a especificação do recurso hierarquias fechadas .