Operadores em C#

Olá pessoal, tudo certo?

Hoje troquei alguns emails com Eric Lippert sobre algumas dúvidas que tive sobre a funcionalidade do overload de operadores em C#. Vou então trazer os casos em que ele me apresentou.

Antes de tudo, vamos ver como funciona o overload de operadores no C#.

Esta funcionalidade permite então ao desenvolvedor utilizar uma notação como resultado = a + b, ao invés de resultado = a.Add(b).

Alguns detalhes sobre overload de operadores.

É sempre interessante ter um método separado que faça a operação e o overload servir como um alias para o método. Isto é necessário porque não são todas as linguagens da CLR que suportam o overload de operadores (corrijam-me se estiver errado!).

Operadores compostos como a += b não são sobreescritos porque são apenas um alias para a = a + b.

O meu problema surgiu nos operadores relacionais, e é onde as coisas ficam diferentes. Pela ideia comum uma operação relacional retorna sempre um valor bool. No entando o retorno dos operadores relacionais pode ser qualquer tipo.

Vamos pensar em uma classe que implemente a interface IComparable<T>, é dedutível que por padrão as operações relacionais >, <, >= e <= sejam possíveis sem a necessidade de fazer o overload destes operadores. No entanto, segundo Lippert, a interface não tem a semântica necessária para que a comparação seja inferida automaticamente, tornando assim necessário implementar os overloads. Sempre que se fizer o overload das operações relacionais, é interessante que a classe implemente IComparable<T>, visto que ela já fornecerá um método de comparação além do operador.

Vamos à outro caso, podemos implementar o override para o método Equals, mas o compilador não entende que == deve fazer a chamada para Equals, sendo então necessário escrever o overload para este operador também.

Algo interessante é que é sempre necessário implementar o par de operadores relacionais, ou seja < >, <= >=, == !=. O que aparenta ser totalmente não intuitivo, visto que != é simplesmente !(a == b), ou seja, o oposto. As coisas não são em assim. Se você voltar um pouco texto, verá que os operadores podem retornar qualquer tipo, incluindo os relacionais, desta forma o compilador não pode afirmar que != é o mesmo que !(a == b). É possível fazer o overload para o operador !, no entanto continua sendo necessário implementar !=.

O fator interessante neste meio é que um operador relacional não retornar um bool é algo estranho, ao menos era o que aparentava para mim, até hoje. Lippert trouxe um exemplo simples e prático de um caso onde poderia ser utilizado um operador relacional sem que o retorno seja um valor bool.

Imaginamos que a comparação execute algum tipo computação alta (comparar duas matrizes 30 x 30), se esta comparação for executada toda vez que o operador for chamado, serão 900 blocos for executados cada vez, ou seja, um uso computacional alto. A ideia é então ter uma espécie de lazy load da operação e só executar a operação quando realmente necessário e armazenando o valor para futuros usos.

Um exemplo de uma operação relacional que é executada de forma assíncrona.

Os fontes estão no github e é isso pessoal, até a proxima!

Anúncios

Um pensamento sobre “Operadores em C#

  1. Concordo com a possibilidade de retornar valores não booleanos nos operadores relacionais, mas acredito que esse tipo tratamento torna a legibilidade do código muito complexa.
    Esse tipo de tratamento, através de criação e chamadas de métodos (da maneira usual) me parece muito mais natural.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s