C# - Sobrecarga de operadores (Operator Overloading)


Sobrecarga (overloading) de operadores !!!

Meu Deus, o que vem a ser isso ????

Se você esta vindo de uma linguagem procedural como Clipper, Dbase , Basic, Cobol, etc. ou se esta começando agora tendo o C# como sua primeira linguagem de programação, pode estranhar o termo. Mas é apenas uma questão de prática.

Sobrecarga (Overload)  é a habilidade de poder definir diversas propriedades, métodos ou procedimentos em uma classe com o mesmo nome mas parâmetros diferentes.

Você entendeu ?

Bem, vou ser mais claro.

Se você criar dois procedimentos em seu aplicativo com o mesmo nome e com parâmetros diferentes estará usando sobrecarga.

Você deve estar se perguntando: "Como posso criar dois procedimentos com o mesmo nome ? Como vou diferenciá-los ? ". Garoto 'experto' você !!!

Você vai diferenciar os métodos/procedimentos pela lista de parâmetros que eles vão possuir , isto é , os métodos/procedimentos terão parâmetros diferentes. Vou dar um exemplo :

Suponha que voce precise criar uma classe com um método que retorne o valor da área de um quadrado , só que este método vai poder aceitar como parâmetro uma string ou um número:

public double CalculaArea(double lado)
{
   return lado * lado;
}
public double CalculaArea(string lado)
{
double ld = 0;
ld = Convert.ToDouble(lado);
return ld * ld;
}

Aqui temos dois métodos com o mesmo nome - CalculaArea - mas que possuem parâmetros diferentes (tipo de dados diferentes) que fornecem o mesmo resultado.

Pois bem, podemos fazer a mesma coisa para operadores na linguagem C#.

A linguagem C#, assim como muitas linguagens orientadas a objetos, permitem a sobrecarga de operadores, ou seja a capacidade de redefinir os operadores de uma classe.

Nem todos os operadores podem ser sobrecarregados, e existem restrições relativas a quando certos operadores podem ser sobrecarregados, como a definição dos operadores == e /=.

Através da sobrecarga de operadores podemos realizar operações complexas através de argumentos de funções e isso nos permite escrever um código muito mais intuitivo e legível.

Para modificar um operador na linguagem C# usamos a seguinte sintaxe:

[modificadores*][type] operator [operator] (parâmetros){(…)}

Os operadores uniários recebem somente um parâmetro e os operadores binários recebem dois parâmetros, sendo que em cada caso um dos parâmetros deve ser do tipo da classe que esta redefinindo o operador.

public static ret-type operator op(parameter-type operand)
{
}
public static ret-type operator op(parameter-type operand1, parameter-type operand1)
{
}
Operador Uniário Operador Binário

Obs: Os operadores redefinidos devem ser public static

Vejamos um exemplo prático onde iremos realizar a sobrecarga do operador ++.

Abra o Visual C# 2010 Express Edition e crie um novo projeto do tipo Console Application com o nome SobreCargaOperadores;

A seguir defina o seguinte código na classe Program.cs:

using System;

namespace SobrecargarOperadores
{
    class Program
    {
        static void Main(string[] args)
        {
            Calculo i = new Calculo(100, 200, 300);
            Calculo j = new Calculo(5, 10, 3);
            i++;
            i.MostraResultado();
            j++; 
            j.MostraResultado();
            Console.WriteLine();
        }
       
    }
    class Calculo
    {
        int a, b, c;
        public Calculo()
        {
            a = b = c = 0;
        }
        public Calculo(int x, int y, int z)
        {
            a = x;
            b = y;
            c = z;
        }
        public static Calculo operator ++(Calculo op1)
        {
            op1.a++;
            op1.b++;
            op1.c++;
            return op1;
        }
        public void MostraResultado()
        {
            Console.WriteLine(a + "," + b + "," + c);
            Console.ReadLine();
        }
    }
}
Aqui criamos a classe Calculo e redefinimos o operador ++
para realizar o incremento em uma unidade dos argumentos recebidos.

Executando o projeto teremos :


Muito simples,não é mesmo ???
 

Vamos agora realizar a sobrecarga de operadores binários para os operadores + , - , / e * (adição, subtração, divisão e multiplicação.)
 

No menu File clique em Add -> Project e a seguir informe o nome OperadoresBInarios;
 

Defina a seguir o código abaixo na classe Program.cs:

using System;

namespace OperadoresBinarios
{
    class Program
    {
        static void Main(string[] args)
        {
            Calculo i = new Calculo(10, 20, 30);
            Calculo j = new Calculo(5, 10, 15);
            Calculo k = new Calculo();
            Console.WriteLine("Sobrecarga de Operadores");
            Console.WriteLine("i = 10, 20, 30");
            Console.WriteLine("j = 5, 10, 15");
            Console.WriteLine();
            //adição
            k = i + j;
            Console.WriteLine("+");
            k.MostraResultado();
            Console.WriteLine();
            //subtração
            k = i - j;
            Console.WriteLine("-");
            k.MostraResultado();
            Console.WriteLine();
            //multiplicação
            k = i * j;
            Console.WriteLine("*");
            k.MostraResultado();
            Console.WriteLine();
            //divisão
            k = i / j;
            Console.WriteLine("/");
            k.MostraResultado();
            Console.WriteLine();
        }
    }
    class Calculo
    {
        int a, b, c;
        public Calculo()
        {
            a = b = c = 0;
        }
        public Calculo(int x, int y, int z)
        {
            a = x;
            b = y;
            c = z;
        }
        public static Calculo operator +(Calculo op1, Calculo op2)
        {
            Calculo calc = new Calculo();
            calc.a = op1.a + op2.a;
            calc.b = op1.b + op2.b;
            calc.c = op1.c + op2.c;
            return calc;
        }
        public static Calculo operator -(Calculo op1, Calculo op2)
        {
            Calculo calc = new Calculo();
            calc.a = op1.a - op2.a;
            calc.b = op1.b - op2.b;
            calc.c = op1.c - op2.c;
            return calc;
        }
        public static Calculo operator *(Calculo op1, Calculo op2)
        {
            Calculo calc = new Calculo();
            calc.a = op1.a * op2.a;
            calc.b = op1.b * op2.b;
            calc.c = op1.c * op2.c;
            return calc;
        }
        public static Calculo operator /(Calculo op1, Calculo op2)
        {
            Calculo calc = new Calculo();
            calc.a = op1.a / op2.a;
            calc.b = op1.b / op2.b;
            calc.c = op1.c / op2.c;
            return calc;
        }
        public void MostraResultado()
        {
            Console.WriteLine(a + "," + b + "," + c);
            Console.ReadLine();
        }
    }
}
Aqui temos a sobrecarga dos operadores +, -, / e * :

Executando o projeto teremos:

Se os operadores de comparação (==) forem sobrecarregados, essa sobrecarga deve ser feita aos pares, ou seja, se for sobrecarregado o operador == também se deve sobrecarregar o operador !=. O mesmo vale para os operadores < e >, e <= e >=.

Outro fato importante é que se por exemplo, você está sobrecarregando o operador == não pode usar (a == b), (a == null) ou (b == null) para verificar a igualdade de referência dentro da sobrecarga.

Isso resulta em uma chamada para o operador sobrecarregado ==, que é o mesmo que voltar a chamar o operador que você está redefinindo e como resultado há um loop infinito. Use ReferenceEquals ou converta o tipo de Objeto para evitar isso.

E estamos conversados...

Pegue o projeto completo aqui: SobrecargarOperadores.zip

1Ts 5:14 Exortamo-vos também, irmãos, a que admoesteis os insubordinados, consoleis os desanimados, ampareis os fracos e sejais longânimos para com todos.

1Ts 5:15 Vede que ninguém dê a outrem mal por mal, mas segui sempre o bem, uns para com os outros, e para com todos.

Referências:


José Carlos Macoratti