Compartilhar via


Sobrecargas de operador

Observação

Esse conteúdo é reimpresso por permissão da Pearson Education, Inc. das Diretrizes de Design da Estrutura: Convenções, Idiomas e Padrões para Bibliotecas .NET Reutilizáveis, 2ª Edição. Essa edição foi publicada em 2008, e desde então o livro foi totalmente revisado na terceira edição. Algumas das informações nesta página podem estar desatualizadas.

As sobrecargas do operador permitem que os tipos de estruturas de dados apareçam como se fossem primitivos internos da linguagem.

Embora permitido e útil em algumas situações, as sobrecargas do operador devem ser usadas com cuidado. Há muitos casos em que a sobrecarga de operador foi abusada, como quando os designers de estrutura começaram a usar operadores para operações que deveriam ser métodos simples. As diretrizes a seguir devem ajudá-lo a decidir quando e como usar a sobrecarga do operador.

❌ EVITE definir sobrecargas de operador, exceto em tipos que devem parecer tipos primitivos (internos).

✔️ CONSIDERE definir sobrecargas de operador em um tipo que deve parecer um tipo primitivo.

Por exemplo, System.String tem operator== e operator!= definido.

✔️ DO define sobrecargas de operador em structs que representam números (como System.Decimal).

❌ NÃO seja engraçadinho ao definir sobrecargas de operador.

A sobrecarga do operador é útil em casos em que é imediatamente óbvio qual será o resultado da operação. Por exemplo, faz sentido ser capaz de subtrair um DateTime de outro DateTime e obter um TimeSpan. No entanto, não é apropriado usar o operador de união lógica para unir duas consultas de banco de dados ou usar o operador shift para gravar em um fluxo.

❌ NÃO forneça sobrecargas de operador, a menos que pelo menos um dos operandos seja do tipo que define a sobrecarga.

✔️ SOBRECARREGUE operadores de maneira simétrica.

Por exemplo, se você sobrecarregar o operator==, também deverá sobrecarregar o operator!=. Da mesma forma, se você sobrecarregar o operator<, você também deverá sobrecarregar o operator>e assim por diante.

✔️ CONSIDERE fornecer métodos com nomes amigáveis que correspondem a cada operador sobrecarregado.

Muitos idiomas não dão suporte à sobrecarga de operador. Por esse motivo, é recomendável que os tipos que sobrecarregam os operadores incluam um método secundário com um nome específico do domínio apropriado que fornece funcionalidade equivalente.

A tabela a seguir contém uma lista de operadores e os nomes de método amigáveis correspondentes.

Símbolo do operador C# Nome dos metadados Nome amigável
N/A op_Implicit To<TypeName>/From<TypeName>
N/A op_Explicit To<TypeName>/From<TypeName>
+ (binary) op_Addition Add
- (binary) op_Subtraction Subtract
* (binary) op_Multiply Multiply
/ op_Division Divide
% op_Modulus Mod or Remainder
^ op_ExclusiveOr Xor
& (binary) op_BitwiseAnd BitwiseAnd
| op_BitwiseOr BitwiseOr
&& op_LogicalAnd And
|| op_LogicalOr Or
= op_Assign Assign
<< op_LeftShift LeftShift
>> op_RightShift RightShift
N/A op_SignedRightShift SignedRightShift
N/A op_UnsignedRightShift UnsignedRightShift
== op_Equality Equals
!= op_Inequality Equals
> op_GreaterThan CompareTo
< op_LessThan CompareTo
>= op_GreaterThanOrEqual CompareTo
<= op_LessThanOrEqual CompareTo
*= op_MultiplicationAssignment Multiply
-= op_SubtractionAssignment Subtract
^= op_ExclusiveOrAssignment Xor
<<= op_LeftShiftAssignment LeftShift
%= op_ModulusAssignment Mod
+= op_AdditionAssignment Add
&= op_BitwiseAndAssignment BitwiseAnd
|= op_BitwiseOrAssignment BitwiseOr
, op_Comma Comma
/= op_DivisionAssignment Divide
-- op_Decrement Decrement
++ op_Increment Increment
- (unary) op_UnaryNegation Negate
+ (unary) op_UnaryPlus Plus
~ op_OnesComplement OnesComplement

Operador de sobrecarga ==

Sobrecarregar operator == é bastante complicado. A semântica do operador precisa ser compatível com vários outros membros, como Object.Equals.

Operadores de conversão

Os operadores de conversão são operadores unários que permitem a conversão de um tipo para outro. Os operadores devem ser definidos como membros estáticos no operando ou no tipo de retorno. Há dois tipos de operadores de conversão: implícito e explícito.

❌ NÃO forneça um operador de conversão se essa conversão não for claramente esperada pelos usuários finais.

❌ NÃO defina operadores de conversão fora do domínio de um tipo.

Por exemplo, Int32, Double e Decimal são todos tipos numéricos, enquanto DateTime não. Portanto, não deve haver nenhum operador de conversão para converter um Double(long) em um DateTime. Um construtor é preferencial nesse caso.

❌ NÃO forneça um operador de conversão implícita se a conversão for potencialmente perdida.

Por exemplo, não deve haver uma conversão implícita de Double para Int32 porque Double tem um intervalo maior do que Int32. Um operador de conversão explícita pode ser fornecido mesmo que a conversão seja potencialmente perdida.

❌ NÃO gere exceções de conversões implícitas.

É muito difícil para os usuários finais entenderem o que está acontecendo, pois talvez eles não estejam cientes de que uma conversão está ocorrendo.

✔️ GERE System.InvalidCastException se uma chamada para um operador de conversão resultar em uma conversão de perda e o contrato do operador não permitir conversões com perda.

Partes © 2005, 2009 Microsoft Corporation. Todos os direitos reservados.

Reimpresso por permissão da Pearson Education, Inc. de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition de Krzysztof Cwalina e Brad Abrams, publicado em 22 de outubro de 2008 pela Addison-Wesley Professional como parte da série Microsoft Windows Development Series.

Consulte também