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.
Sugestão
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.
Uma deconstruction atribui as partes individuais de um valor — os seus componentes — a múltiplas variáveis numa única operação. Os componentes de uma tupla são os seus elementos, expostos pela posição. Outro tipo pode expor componentes ao definir o método Deconstruct.
Registos posicionais, que declaram as suas propriedades como parâmetros semelhantes a construtores, recebem automaticamente um método Deconstruct.
Desconstruir tuplas
Suponha que um método devolve uma tupla com dados da cidade. Pode ler cada componente um de cada vez:
var cityData = QueryCityData("New York City");
var city = cityData.City;
var population = cityData.Population;
var area = cityData.Area;
Uma deconstruction atribui esses componentes numa etapa:
(string city, int population, double area) = QueryCityData("New York City");
Também pode deixar C# inferir os tipos de variáveis:
var (city, population, area) = QueryCityData("New York City");
Uma desconstrução pode misturar variáveis existentes, variáveis recém-declaradas e descartes numa única atribuição:
(city, var population, _) = QueryCityData("New York City");
Escolha a forma que torne o código mais fácil de ler. Um único var antes dos parênteses é frequentemente a forma mais clara inferida. Também podes misturar tipos explícitos e var dentro dos parênteses, mas essa forma costuma ser mais difícil de percorrer rapidamente. Se precisares apenas de alguns valores, usa descartáveis em vez de omitir posições.
Ignorar valores desnecessários com descartes
Cada valor produzido deve alinhar-se com uma posição no lado esquerdo da atribuição. Quando não precisares de uma ou mais posições, usa _ como descarte:
var (_, _, population1960, _, population2010) = QueryPopulationDataForYears(
"New York City", 1960, 2010);
Aqui, a tupla devolve o nome da cidade, dois anos e dois valores populacionais. A desconstrução mantém apenas os valores populacionais porque o cálculo utiliza apenas esses componentes.
Desconstruir tipos definidos pelo utilizador
Uma classe, estrutura ou interface pode suportar a desconstrução ao declarar um método Deconstruct. Cada componente torna-se um out parâmetro, o que permite ao método atribuir um valor de volta à variável do chamador sem o devolver. Como cada componente é devolvido através de um parâmetro out, o próprio método devolve void:
public void Deconstruct(out string firstName, out string middleName, out string lastName)
{
firstName = FirstName;
middleName = MiddleName;
lastName = LastName;
}
Pode então desestruturar uma instância diretamente:
var (firstName, middleName, lastName) = passenger;
Um tipo pode fornecer múltiplas Deconstruct sobrecargas com diferentes aridades — o número de out parâmetros declarados pelo método — para que os chamadores possam escolher quantos componentes recuperar:
public void Deconstruct(out string firstName, out string lastName)
{
firstName = FirstName;
lastName = LastName;
}
public void Deconstruct(out string firstName, out string middleName, out string lastName)
{
firstName = FirstName;
middleName = MiddleName;
lastName = LastName;
}
public void Deconstruct(out string firstName, out string lastName, out string city, out string state)
{
firstName = FirstName;
lastName = LastName;
city = City;
state = State;
}
Duas sobrecargas com o mesmo número de out parâmetros são ambíguas. O compilador reporta um erro para a chamada ambígua, por isso distinga as sobrecargas pela aridade, não apenas pelos tipos de parâmetros.
Os descartes também funcionam com desmontagem definida pelo utilizador. Para mais informações sobre descartes em geral, veja Descartes e o padrão de descarte:
var (firstName, _, city, _) = passenger;
Desconstruir registos
Um posicional record struct ou record declara as suas propriedades como parâmetros na própria declaração do tipo, semelhante a um construtor. O compilador gera um Deconstruct método para si, com out parâmetros que correspondem a esses parâmetros de posição:
var (city, highTempC, lowTempC) = forecast;
Apenas os parâmetros posicionais participam nessa desestruturação gerada. As propriedades adicionais que declarar noutro local do registo não são adicionadas automaticamente.
Desestruturar tipos que não lhe pertencem
Se não puder modificar um tipo, ainda pode suportar a desconstrução escrevendo um método de extensão — um método estático que adiciona um Deconstruct método a um tipo que não lhe pertence, como se fosse um membro desse tipo. Depois de adicionar o método, qualquer valor Uri pode usar a sintaxe de desconstrução:
static class UriExtensions
{
public static void Deconstruct(this Uri uri, out string scheme, out string host, out int port)
{
scheme = uri.Scheme;
host = uri.Host;
port = uri.Port;
}
}
A mesma regra de ambiguidade aplica-se aqui: dois métodos de extensão Deconstruct com a mesma aridade são ambíguos. Também pode surgir ambiguidade entre um método de instância Deconstruct e um método de extensão da mesma aridade. Em qualquer dos casos, o compilador reporta um erro para a chamada ambígua.
Desconstrução integrada em tipos do sistema
Alguns tipos de sistema já definem um Deconstruct método, usando o mesmo mecanismo que usarias para os teus próprios tipos. Por exemplo, System.Collections.Generic.KeyValuePair<TKey,TValue> suporta a desconstrução, o que torna a iteração do dicionário concisa:
foreach (var (repo, commitCount) in repoCommitCounts)
{
Console.WriteLine($"{repo} had {commitCount:N0} commits in this snapshot.");
}
Desconstrução e comparação de padrões
Um Deconstruct método também permite padrões posicionais para esse tipo. Um padrão posicional testa e desconstrói um valor num passo, usando a mesma sintaxe entre parênteses que uma desconstrução: person is ("Alice", 30) corresponde a um/uma Person cujos componentes desconstruídos são iguais a esses valores. Isto é diferente de um padrão de propriedades, que testa diretamente propriedades nomeadas, como person is { Name: "Alice", Age: 30 }. Os padrões de propriedades são geralmente mais claros para formas de objetos porque os nomes dos membros explicam o teste. Os padrões posicionais são mais fortes quando a ordem já carrega o significado, como acontece com tuplas ou outros valores ordenados pequenos.