Da trilha de C# Este conceito ainda não saiu como card do dia. ir para o card de hoje

C# Tipos Intermediário

Structs vs classes

Em C#, structs e classes são tipos de dados, mas com semântica diferente. Classes são tipos de referência: a variável guarda um endereço para o objeto na heap. Structs são tipos de valor: a variável guarda os dados diretamente, geralmente na pilha (ou inline no objeto que a contém).

Isso significa que atribuir uma struct copia todos os campos, enquanto atribuir uma classe copia a referência. Modificar a cópia de uma struct não afeta o original; modificar o objeto apontado por uma referência afeta ambos.

Structs não podem herdar de outra struct ou classe (exceto System.ValueType), não podem ter construtor sem parâmetros explícito (antes do C# 10) e são seladas. Classes suportam herança, polimorfismo e podem ser null.

Use struct para tipos pequenos (geralmente ≤ 16 bytes), imutáveis e de vida curta, como DateTime, Guid, Point. Use readonly struct para garantir imutabilidade e evitar cópias desnecessárias. Use class quando precisar de identidade, herança ou comportamento polimórfico.

Pontos-chave

  • Structs têm semântica de valor: atribuições copiam os dados; classes têm semântica de referência: atribuições copiam o endereço.
  • readonly struct impede que os campos sejam modificados após a construção, evitando efeitos colaterais em cópias.
  • Structs são mais eficientes para pequenos dados imutáveis, pois evitam alocação na heap e coleta de lixo.
  • Classes são preferíveis quando há herança, polimorfismo, identidade ou estado mutável compartilhado.
  • Cuidado: structs mutáveis podem causar bugs ao serem passadas como argumento ou armazenadas em coleções.
StructVsClass.cs
using System;

// Struct: tipo de valor (cópia independente)
public struct PontoStruct
{
    public int X;
    public int Y;

    public PontoStruct(int x, int y)
    {
        X = x;
        Y = y;
    }

    public override string ToString() => $"({X}, {Y})";
}

// Class: tipo de referência (compartilha o mesmo objeto)
public class PontoClass
{
    public int X;
    public int Y;

    public PontoClass(int x, int y)
    {
        X = x;
        Y = y;
    }

    public override string ToString() => $"({X}, {Y})";
}

class Program
{
    static void Main()
    {
        // Struct: atribuição copia os valores
        PontoStruct s1 = new PontoStruct(1, 2);
        PontoStruct s2 = s1; // cópia independente
        s2.X = 99;
        Console.WriteLine($"Struct: s1 = {s1}, s2 = {s2}");

        // Class: atribuição copia a referência
        PontoClass c1 = new PontoClass(1, 2);
        PontoClass c2 = c1; // mesma referência
        c2.X = 99;
        Console.WriteLine($"Class:  c1 = {c1}, c2 = {c2}");
    }
}

Exercícios

  1. 1
    Fácil

    Criando e comparando structs

    Crie uma struct chamada Retangulo com campos Largura e Altura (double). No Main, crie dois retângulos, atribua um ao outro, modifique a cópia e imprima ambos para mostrar que são independentes.

    Resolver
  2. 2
    Médio

    readonly struct imutável

    Transforme a struct Retangulo em readonly struct com propriedades somente leitura. Adicione um método ComLargura(double novaLargura) que retorna um novo Retangulo com a largura alterada, sem modificar o original. Demonstre no Main.

    Resolver
  3. 3
    Desafio

    Escolhendo entre struct e class

    Implemente duas versões de um contador: ContadorStruct (struct) e ContadorClass (class), ambos com um campo Valor e método Incrementar(). No Main, crie um array de cada tipo, incremente cada elemento e imprima os valores para demonstrar a diferença de comportamento em coleções.

    Resolver

Continue estudando