0Pricing
C# Academy · Aula

Boas práticas para sobrecarga de operadores

Mantenha os operadores sobrecarregados intuitivos.

Boas práticas para sobrecarga de operadores é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 4 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.

Boas práticas para sobrecarga de operadores

A sobrecarga de operadores é uma ferramenta poderosa. Quando bem usada, torna os tipos de valor intuitivos; quando mal usada, torna o código enigmático. Esta lição aborda princípios que mantêm os operadores sobrecarregados previsíveis.

Sobrecarregue apenas quando o significado for óbvio

Sobrecarregue um operador somente quando seu significado for inequívoco para o seu tipo. + em um vetor significa claramente uma adição componente a componente; + em um Order apenas confundiria os leitores.

using System;

public struct Vector2
{
    public int X, Y;
    public Vector2(int x, int y) { X = x; Y = y; }
    // + means adding components: obvious and expected
    public static Vector2 operator +(Vector2 a, Vector2 b)
        => new Vector2(a.X + b.X, a.Y + b.Y);
    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Vector2(1, 2) + new Vector2(3, 4));
    }
}

Preserve as expectativas matemáticas

Mantenha os operadores de acordo com a intuição: a + b deve ser igual a b + a quando a matemática for comutativa, e + não deve subtrair secretamente. Surpresas desse tipo causam erros sutis.

using System;

public struct Money
{
    public decimal Amount;
    public Money(decimal a) { Amount = a; }
    public static Money operator +(Money a, Money b) => new Money(a.Amount + b.Amount);
    public override string ToString() => "$" + Amount;
}

public class Program
{
    public static void Main()
    {
        var x = new Money(3);
        var y = new Money(5);
        Console.WriteLine((x + y).Amount == (y + x).Amount); // commutative
    }
}

Mantenha a simetria e os pares

A linguagem combina determinados operadores, mas você também deve manter a simetria lógica: se adicionar +, considere -; se adicionar <, forneça também > e as variantes com igualdade. Conjuntos de operadores incompletos frustram os usuários.

using System;

public struct Length
{
    public int Mm;
    public Length(int mm) { Mm = mm; }
    public static Length operator +(Length a, Length b) => new Length(a.Mm + b.Mm);
    public static Length operator -(Length a, Length b) => new Length(a.Mm - b.Mm);
    public override string ToString() => Mm + "mm";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Length(50) + new Length(20));
        Console.WriteLine(new Length(50) - new Length(20));
    }
}

Não altere os operandos

Os operadores devem ser puros: calcular e retornar um novo valor, deixando os operandos intactos. Alterar um operando dentro de + quebra todas as expectativas do leitor.

using System;

public struct Vector2
{
    public int X, Y;
    public Vector2(int x, int y) { X = x; Y = y; }
    public static Vector2 operator +(Vector2 a, Vector2 b)
        => new Vector2(a.X + b.X, a.Y + b.Y); // returns new, mutates nothing
    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        var a = new Vector2(1, 1);
        var unused = a + new Vector2(9, 9);
        Console.WriteLine("a is still " + a);
    }
}

Mantenha == consistente com Equals

Uma boa prática recorrente: sempre que sobrecarregar ==, substitua Equals e GetHashCode para que todos os caminhos de igualdade concordem. A inconsistência nesse ponto é um dos erros mais comuns em operadores.

using System;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public override bool Equals(object obj) => obj is Point p && p.X == X && p.Y == Y;
    public override int GetHashCode() => HashCode.Combine(X, Y);
    public static bool operator ==(Point a, Point b) => a.Equals(b);
    public static bool operator !=(Point a, Point b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Point(1, 1) == new Point(1, 1));
    }
}

Forneça alternativas nomeadas

Algumas linguagens e ferramentas de análise não conseguem usar operadores. Oferecer um método com nome explícito, como Add, junto com +, melhora a interoperabilidade e a facilidade de descoberta.

using System;

public struct Vector2
{
    public int X, Y;
    public Vector2(int x, int y) { X = x; Y = y; }
    public Vector2 Add(Vector2 other) => new Vector2(X + other.X, Y + other.Y);
    public static Vector2 operator +(Vector2 a, Vector2 b) => a.Add(b);
    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        var v = new Vector2(1, 2);
        Console.WriteLine(v.Add(new Vector2(3, 4)));
        Console.WriteLine(v + new Vector2(3, 4));
    }
}

Prefira operadores em tipos semelhantes a valores

Os operadores parecem naturais em tipos imutáveis semelhantes a valores (estruturas ou classes semelhantes a registros). Para tipos mutáveis e fortemente baseados em identidade, métodos nomeados geralmente comunicam melhor a intenção.

using System;

public readonly struct Rational
{
    public readonly int Num, Den;
    public Rational(int n, int d) { Num = n; Den = d; }
    public static Rational operator *(Rational a, Rational b)
        => new Rational(a.Num * b.Num, a.Den * b.Den);
    public override string ToString() => Num + "/" + Den;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Rational(1, 2) * new Rational(2, 3));
    }
}

Documente os casos extremos

Seja explícito sobre como os operadores lidam com valores especiais: divisão por zero, operandos nulos para classes ou estouro. Um tratamento previsível evita que os chamadores sejam pegos de surpresa.

using System;

public struct SafeDiv
{
    public int Value;
    public SafeDiv(int v) { Value = v; }
    // Documented behavior: dividing by zero yields zero
    public static SafeDiv operator /(SafeDiv a, SafeDiv b)
        => new SafeDiv(b.Value == 0 ? 0 : a.Value / b.Value);
    public override string ToString() => Value.ToString();
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new SafeDiv(10) / new SafeDiv(0));
        Console.WriteLine(new SafeDiv(10) / new SafeDiv(2));
    }
}

Um conjunto disciplinado de operadores

Um tipo numérico bem elaborado combina alguns operadores intuitivos, igualdade consistente e imutabilidade. O resultado se comporta como um número integrado e é agradável de usar.

using System;

public readonly struct Vec
{
    public readonly double X, Y;
    public Vec(double x, double y) { X = x; Y = y; }
    public static Vec operator +(Vec a, Vec b) => new Vec(a.X + b.X, a.Y + b.Y);
    public static Vec operator -(Vec a, Vec b) => new Vec(a.X - b.X, a.Y - b.Y);
    public static Vec operator *(Vec a, double k) => new Vec(a.X * k, a.Y * k);
    public override string ToString() => "(" + X + ", " + Y + ")";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine((new Vec(1, 2) + new Vec(3, 4)) * 2);
    }
}

Experimente você mesmo

Reúna as práticas: um tipo de valor imutável, operadores intuitivos, uma alternativa nomeada e igualdade consistente.

using System;

public readonly struct Meters : IEquatable<Meters>
{
    public readonly double Value;
    public Meters(double v) { Value = v; }
    public Meters Add(Meters other) => new Meters(Value + other.Value);
    public static Meters operator +(Meters a, Meters b) => a.Add(b);
    public bool Equals(Meters other) => Value == other.Value;
    public override bool Equals(object obj) => obj is Meters m && Equals(m);
    public override int GetHashCode() => Value.GetHashCode();
    public static bool operator ==(Meters a, Meters b) => a.Equals(b);
    public static bool operator !=(Meters a, Meters b) => !a.Equals(b);
    public override string ToString() => Value + "m";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Meters(3) + new Meters(4));
        Console.WriteLine(new Meters(7) == new Meters(7));
    }
}

Verificação rápida

Aplique as boas práticas para operadores.

Recapitulação

Uma boa sobrecarga de operadores é disciplinada e previsível.

  • Sobrecarregue apenas quando o significado for óbvio.
  • Preserve as expectativas matemáticas e a simetria.
  • Mantenha a pureza: retorne novos valores e nunca altere os operandos.
  • Mantenha == consistente com Equals/GetHashCode.
  • Ofereça alternativas nomeadas e prefira tipos semelhantes a valores.

Perguntas Frequentes

A aula “Boas práticas para sobrecarga de operadores” é grátis?

Sim — o texto completo de “Boas práticas para sobrecarga de operadores” é 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 “Boas práticas para sobrecarga de operadores”?

Mantenha os operadores sobrecarregados intuitivos. 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 4 de 4.

Quanto tempo leva a aula “Boas práticas para sobrecarga de operadores”?

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. Sobrecarga de operadores aritméticos
  2. Sobrecarga de operadores de comparação
  3. Conversões definidas pelo usuário
  4. Boas práticas para sobrecarga de operadores
← Voltar para C# Academy