Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Tip
Este artigo faz parte da secção Fundamentos para programadores que já conhecem pelo menos uma linguagem de programação e estão a aprender C#. Começa com a visão geral de correspondência de moldes se os moldes forem novos para ti. Para regras completas de compatibilidade, consulte padrões de declaração e tipos na referência da linguagem.
Um padrão de tipo é aplicado a uma expressão de entrada. C# avalia a expressão, depois testa se o valor resultante não é nulo e se o seu tipo de execução é compatível com o tipo especificado. Um padrão de tipo apenas indica se o teste de tipo é bem-sucedido. Não declara uma variável.
Faz uma pergunta do tipo simor-no
Num sistema de entrega, IRouteStop é um contrato de capacidades para destinos aceites pelo planeamento de rotas.
CanRoute testa se o destino avaliado tem essa capacidade, e o seu resultado booleano determina se o destino entra no fluxo de trabalho de planeamento de rotas. O fluxo de trabalho precisa apenas de uma resposta sim ou não e não lê quaisquer membros de paragem da rota, pelo que um padrão de tipo sem variável capturada é adequado.
static bool CanRoute(object? destination) =>
destination is IRouteStop;
A expressão de entrada é destination, e IRouteStop é o tipo a ser testado. Escolhe um padrão de tipo quando a resposta for apenas sim ou não. Se o ramo correspondente precisar de ler um endereço ou chamar outro membro através de IRouteStop, escolha antes um padrão de declaração, para que o ramo tenha uma variável desse tipo.
Note
Também podes ver destination is IRouteStop _. Esta sintaxe é um padrão de declaração em que _ significa que nenhuma variável é retida. Realiza o mesmo teste de tipo quando ambas as formas são válidas, mas destination is IRouteStop declara a intenção apenas do teste de forma mais direta.
Classes de correspondência e interfaces
No sistema de entrega, IRouteStop define o contrato de capacidades para destinos de planeamento de percurso, enquanto RouteStop é uma classe base que fornece dados comuns de paragem de percurso e a respetiva implementação.
ExpressRouteStop é uma classe especializada derivada de RouteStop. O exemplo testa um valor avaliado para que a sua saída possa demonstrar os três tipos compatíveis. Cada teste necessita apenas de um resultado booleano, pelo que não é necessária nenhuma variável capturada.
interface IRouteStop { }
abstract class RouteStop(string street) : IRouteStop
{
public string Street { get; } = street;
public string GetDisplayName() => Street;
}
sealed class ExpressRouteStop(string street) : RouteStop(street)
{
}
static void ShowCompatibility()
{
object destination = new ExpressRouteStop("8 Oak Avenue");
Console.WriteLine($"Exact class: {destination is ExpressRouteStop}");
Console.WriteLine($"Base class: {destination is RouteStop}");
Console.WriteLine($"Interface: {destination is IRouteStop}");
}
O valor avaliado é um ExpressRouteStop. A saída mostra que corresponde exatamente à sua classe, à sua RouteStop classe base e à IRouteStop interface que RouteStop implementa.
Para regras detalhadas de compatibilidade e casos extremos, consulte a referência do padrão de tipos.
Vários tipos de percurso
Num sistema de apoio, SupportRequest é a classe base para classes especializadas de pedidos como PasswordResetRequest e BillingQuestion. Um ramo de switch associa um padrão ao resultado a devolver quando esse padrão corresponde. Cada braço devolve o nome de uma fila de processamento, e o braço final fornece uma fila de retenção para outros valores avaliados. A fila selecionada depende apenas do tipo em tempo de execução do valor avaliado, pelo que os padrões de tipo são adequados, porque nenhum membro do pedido é lido.
static string RouteRequest(object request) =>
request switch
{
PasswordResetRequest => "Identity queue",
BillingQuestion => "Billing queue",
SupportRequest => "General support queue",
_ => "Intake queue"
};
Cada ramo responde a uma pergunta do tipo e devolve a fila que processa esse pedido. Se um braço precisar de ler membros do pedido, use um padrão de declaração para capturar o valor correspondente numa variável.
Os braços dos interruptores são considerados de cima para baixo. Coloca uma classe especializada antes da classe base. Caso contrário, o braço da classe base pode corresponder a todas as instâncias da classe especializada, o que torna o braço posterior inacessível.
Opcional: usar um parâmetro de tipo como tipo testado
Este exemplo opcional baseia-se em tipos e métodos genéricos. Um parâmetro de tipo como TRequest é um marcador de posição para um tipo fornecido pelo chamador. Um lote de pedidos recebidos pode conter vários tipos de pedidos, e o chamador fornece ConfidentialRequest para testar se algum pedido necessita de tratamento confidencial. O resultado Booleano seleciona o tratamento confidencial para todo o lote e produz uma mensagem de estado visível. Um padrão de tipo com um parâmetro de tipo encaixa porque só a existência de um pedido correspondente importa, pelo que o objeto correspondente não precisa de ser retido.
static void ShowConfidentialBatchHandling()
{
object[] incomingRequests = [new BillingQuestion(), new ConfidentialRequest()];
bool requiresConfidentialHandling =
ContainsRequestOfType<ConfidentialRequest>(incomingRequests);
Console.WriteLine(requiresConfidentialHandling
? "Send the entire batch to confidential handling."
: "Send the batch to standard handling.");
}
static bool ContainsRequestOfType<TRequest>(IEnumerable<object> requests)
{
foreach (object request in requests)
{
if (request is TRequest)
{
return true;
}
}
return false;
}
Se o autor da chamada precisasse do próprio pedido correspondente, seria mais apropriada uma operação de pesquisa ou de filtragem que devolvesse itens correspondentes.