0Pricing
C# Academy · Aula

Igualdade de valores e desconstrução

Entenda a igualdade estrutural de records, substitua Equals/GetHashCode e use padrões de desconstrução.

Igualdade de valores e desconstrução é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.

Análise detalhada da igualdade de registros

Os registros geram automaticamente Equals, GetHashCode e os operadores ==/!=, que comparam estruturalmente todas as propriedades. Entender esse funcionamento ajuda você a usar registros corretamente e a substituí-lo quando necessário.

Como funciona a igualdade gerada automaticamente

O compilador gera código que compara cada propriedade usando EqualityComparer<T>.Default. Para propriedades de tipos de referência, isso usa o próprio Equals — não a igualdade por referência.

public record Address(string Street, string City);
public record Person(string Name, Address HomeAddress);

var a = new Person("Alice", new Address("123 Main", "NYC"));
var b = new Person("Alice", new Address("123 Main", "NYC"));

Console.WriteLine(a == b); // True — deep structural equality
// Equality checks:
// Name: "Alice" == "Alice" ✓
// HomeAddress: compares Address properties recursively ✓

Substituindo a igualdade gerada

Você pode substituir Equals e GetHashCode em um registro quando quiser uma lógica de igualdade personalizada — por exemplo, comparando somente um subconjunto das propriedades.

public record Customer(int Id, string Name, string Email)
{
    // Consider customers equal if they have the same ID,
    // regardless of name or email changes
    public virtual bool Equals(Customer? other)
        => other is not null && Id == other.Id;

    public override int GetHashCode() => Id.GetHashCode();
}

Registros em coleções

Como os registros implementam IEquatable<T> com igualdade estrutural, eles funcionam corretamente como chaves de dicionário, em HashSets e com Distinct e GroupBy do LINQ.

public record Tag(string Name, string Color);

var tags = new List<Tag>
{
    new("C#", "blue"), new("C#", "blue"), new("dotnet", "purple")
};

var unique = tags.Distinct().ToList(); // [Tag(C#, blue), Tag(dotnet, purple)]

var set = new HashSet<Tag>(tags);
set.Contains(new Tag("C#", "blue")); // true

Desconstrução: conceitos básicos

Os registros posicionais geram automaticamente um método Deconstruct com parâmetros out para cada propriedade posicional. Isso permite uma extração semelhante à de tuplas.

public record Point(double X, double Y);
public record RGB(byte R, byte G, byte B);

var p = new Point(3.0, 4.0);
var (x, y) = p; // deconstruct
Console.WriteLine($"{x}, {y}");

var color = new RGB(255, 128, 0);
var (r, g, b) = color;
Console.WriteLine($"R={r}, G={g}, B={b}");

Desconstrução na correspondência de padrões

Registros desconstruídos em expressões de seleção permitem uma poderosa correspondência de padrões posicionais.

public record Point(int X, int Y);

string Classify(Point p) => p switch
{
    (0, 0)           => "Origin",
    (int x, 0)       => $"X-axis at {x}",
    (0, int y)       => $"Y-axis at {y}",
    (int x, int y) when x == y => $"Diagonal at {x}",
    (int x, int y)   => $"Point ({x}, {y})"
};

Console.WriteLine(Classify(new Point(0, 0)));  // Origin
Console.WriteLine(Classify(new Point(3, 3)));  // Diagonal at 3

Métodos Deconstruct personalizados

Registros não posicionais (e qualquer classe) podem adicionar manualmente um método Deconstruct. Métodos de extensão também podem adicionar desconstrução a tipos existentes.

public class Temperature
{
    public double Celsius { get; }
    public Temperature(double c) => Celsius = c;

    // Manual Deconstruct
    public void Deconstruct(out double celsius, out double fahrenheit)
    {
        celsius    = Celsius;
        fahrenheit = Celsius * 9 / 5 + 32;
    }
}

var t = new Temperature(100);
var (c, f) = t;
Console.WriteLine($"{c}°C = {f}°F"); // 100°C = 212°F

Ignorando partes da desconstrução

Use descartes (_) para ignorar partes indesejadas de uma desconstrução — de forma semelhante aos descartes de tuplas.

public record Order(int Id, string Customer, decimal Total, DateTime Date);

var order = new Order(42, "Alice", 99.99m, DateTime.UtcNow);

// Only want Id and Total
var (id, _, total, _) = order;
Console.WriteLine($"Order {id}: ${total}");

// In switch: ignore some fields
string Classify(Order o) => o switch
{
    (_, _, > 1000, _) => "High value",
    (_, _, > 100, _)  => "Medium value",
    _                 => "Low value"
};

Padrões de propriedade versus padrões posicionais

Os registros oferecem suporte tanto a padrões posicionais (por posição) quanto a padrões de propriedade (por nome). Os padrões de propriedade são mais legíveis em registros com muitas propriedades.

public record Order(int Id, string Status, decimal Total);

// Positional pattern:
string DescribePos(Order o) => o switch
{
    (_, "Shipped", > 100) => "High-value shipped",
    _                     => "Other"
};

// Property pattern (more readable):
string DescribeProp(Order o) => o switch
{
    { Status: "Shipped", Total: > 100 } => "High-value shipped",
    { Status: "Cancelled" }             => "Cancelled",
    _                                   => "Other"
};

No mundo real: padrão de tipo Result

Um tipo de resultado no estilo de união discriminada usando registros e desconstrução — uma abordagem funcional para o tratamento de erros.

public abstract record Result<T>;
public record Success<T>(T Value) : Result<T>;
public record Failure<T>(string Error) : Result<T>;

Result<Order> PlaceOrder(CreateOrderRequest req)
{
    if (req.Quantity <= 0)
        return new Failure<Order>("Quantity must be positive");
    var order = CreateOrder(req);
    return new Success<Order>(order);
}

// Consuming:
var result = PlaceOrder(request);
switch (result)
{
    case Success<Order>(var order):
        return Results.Created($"/orders/{order.Id}", order);
    case Failure<Order>(var error):
        return Results.BadRequest(error);
}

Verificação rápida

O que usar um descarte (_) em uma expressão de desconstrução faz?

Recapitulação: igualdade por valor e desconstrução

Principais conclusões:

  • A igualdade gerada automaticamente compara todas as propriedades de forma estrutural e recursiva
  • Substitua Equals/GetHashCode nos registros para implementar uma lógica de identidade personalizada
  • Os registros funcionam corretamente como elementos de HashSet e chaves de dicionário
  • Os registros posicionais geram automaticamente a desconstrução — use var (a, b) = record
  • Os descartes (_) ignoram valores posicionais indesejados na desconstrução
  • Os padrões de propriedade ({Status: "X"}) são mais legíveis que os padrões posicionais para registros complexos

Perguntas Frequentes

A aula “Igualdade de valores e desconstrução” é grátis?

Sim — o texto completo de “Igualdade de valores e desconstrução” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.

O que vou aprender em “Igualdade de valores e desconstrução”?

Entenda a igualdade estrutural de records, substitua Equals/GetHashCode e use padrões de desconstrução. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Igualdade de valores e desconstrução”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Tipos record: fundamentos e sintaxe
  2. Imutabilidade com init e with
  3. Igualdade de valores e desconstrução
  4. Records no design orientado a domínios
← Voltar para C# Academy