C# -  Sobrecarga de operadores de conversão


 Hoje vamos recordar o que são e como usar os operadores implícitos e explícitos e qual a diferença para a sobrecarga de operadores de conversão na linguagem C#,

Em C#, operadores implícitos e explícitos são operadores de conversão que permitem converter um tipo de dados em outro. Eles são essenciais para garantir a flexibilidade e a segurança do código ao lidar com diferentes representações de dados.

Operadores implícitos

Operadores implícitos são aqueles que o compilador pode realizar automaticamente, sem a necessidade de uma conversão explícita. Por exemplo, a atribuição de uma variável do tipo int a uma variável do tipo long é uma conversão implícita.


int int = 10;
// Conversão implícita de int para long
long longo = inteiro;
 

Exemplos de operadores implícitos

Mais exemplos de Conversões Implícitas Comuns:

Numéricas:
   byte para short, int, long, float, double, decimal
   short para int, long, float, double, decimal
   char para ushort, int, long, float, double, decimal
   int para long, float, double, decimal
   long para float, double, decimal
   float para double

Referência:
   De uma classe derivada para sua classe base.
   De uma classe que implementa uma interface para essa interface.
   string para object (todos os tipos derivam de object).

Operadores explícitos são aqueles que o desenvolvedor deve explicitar, usando a sintaxe (tipo) antes do valor a ser convertido. Por exemplo, a atribuição de uma variável do tipo int a uma variável do tipo float usando um cast explícito é feito da seguinte forma:

double numeroDouble = 10.5;
 // Conversão explícita de double par
int numeroInteiro = (int)numeroDouble;

Exemplos de operadores explícitos

Mais exemplos de Conversões Explícitas Comuns:

Numéricas:
  double para float, long, int, short, byte, char
  float para long, int, short, byte, char
  long para int, short, byte, char
  int para short, byte, char
  short para byte, char
  decimal para qualquer tipo numérico (e vice-versa, exceto float e double).

Referência:
  De uma classe base para uma classe derivada (requer verificação em tempo de execução, como is ou as).
  De uma interface para uma classe que a implementa.

Sobrecarga de operadores de conversão

A sobrecarga de operadores de conversão é a capacidade de definir um operador de conversão personalizado para um tipo de dados personalizado. Isso permite que os desenvolvedores definam o comportamento de um operador de conversão para seus próprios tipos de dados, o que pode tornar o código mais conciso e expressivo.

Esses operadores permitem que você defina como os objetos de uma classe podem ser implicitamente ou explicitamente convertidos para outros tipos.

Operador Implícito (implicit operator):

Este operador é usado para realizar conversões implícitas entre tipos sendo geralmente utilizado quando a conversão não resulta em perda de dados.

Sintaxe:
public static implicit operator TipoDestino(TipoOrigem objetoOrigem)
{
     // Lógica de conversão
    return novoObjetoTipoDestino;
}

Exemplo: Imagine que você tem uma classe TemperaturaCelsius e quer que ela possa ser implicitamente convertida para um double.

public class TemperaturaCelsius
{
    public double Valor { get; private set; }
    public TemperaturaCelsius(double valor)
    {
        Valor = valor;
    }
    // Operador implícito para converter TemperaturaCelsius para double
    public static implicit operator double(TemperaturaCelsius temp)
    {
        return temp.Valor;
    }
}
// Uso:
TemperaturaCelsius tempC = new TemperaturaCelsius(25.5);
double valorDouble = tempC; // Conversão implícita
Console.WriteLine($"Temperatura em double: {valorDouble}"); 
// Saída: Temperatura em double: 25.5

Neste exemplo, a conversão de TemperaturaCelsius para double é considerada segura e óbvia, pois double pode representar o valor de TemperaturaCelsius sem perda.

Operador Explícito (explicit operator):

Este operador é usado para realizar conversões explícitas entre tipos e é geralmente é utilizado quando há a possibilidade de perda de dados ou quando a conversão não é óbvia.

Sintaxe:
public static explicit operator TipoDestino(TipoOrigem objetoOrigem)
{
   // Lógica de conversão
   return novoObjetoTipoDestino;
}

Continuando com o exemplo da temperatura, se você quisesse converter um double diretamente para TemperaturaCelsius, talvez fosse melhor uma conversão explícita, pois o double pode não ser necessariamente uma temperatura.

public class TemperaturaCelsius
{
    public double Valor { get; private set; }
    public TemperaturaCelsius(double valor)
    {
        Valor = valor;
    }
    // Operador explícito para converter double para TemperaturaCelsius
    public static explicit operator TemperaturaCelsius(double valorDouble)
    {
        return new TemperaturaCelsius(valorDouble);
    }
}
// Uso:
double tempDouble = 30.0;
TemperaturaCelsius tempC2 = (TemperaturaCelsius)tempDouble; // Conversão explícita
Console.WriteLine($"Temperatura de double para Celsius: {tempC2.Valor}"); 
// Saída: Temperatura de double para Celsius: 30

A distinção entre implicit operator e explicit operator é crucial para a clareza e a segurança do seu código:

implicit operator: Use quando a conversão é segura, sem perda de dados e intuitiva. Pense: "Isso sempre faz sentido e não vai surpreender o usuário do meu tipo?"

explicit operator: Use quando a conversão pode resultar em perda de dados ou quando não é imediatamente óbvia. Isso força o desenvolvedor a reconhecer e aceitar o risco da conversão.

Desta forma  implicit operator é usado para conversões implícitas entre tipos, enquanto explicit operator é usado para conversões explícitas, geralmente quando há a possibilidade de perda de dados.

E estamos conversados...

"A minha alma espera somente em Deus; dele vem a minha salvação.
Só ele é a minha rocha e a minha salvação; é a minha defesa; não serei grandemente abalado"
Salmos 62:1,2

Referências:


José Carlos Macoratti