Partilhar via


Sobrecargas do operador

Nota

Este conteúdo é reimpresso com permissão da Pearson Education, Inc., a partir de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Essa edição foi publicada em 2008 e, desde então, o livro foi totalmente revisto na terceira edição. Algumas das informações nesta página podem estar desatualizadas.

As sobrecargas de operador permitem que os tipos de estrutura apareçam como se fossem primitivos de linguagem incorporados.

Embora permitidas e úteis em algumas situações, as sobrecargas do operador devem ser usadas com cautela. Há muitos casos em que a sobrecarga do operador foi abusiva, como quando os projetistas de estruturas 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 primitivos (internos).

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

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

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

❌ NÃO seja fofo ao definir sobrecargas de operador.

A sobrecarga do operador é útil nos casos em que é imediatamente óbvio qual será o resultado da operação. Por exemplo, faz sentido ser capaz de subtrair um DateTime do 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 do operador, a menos que pelo menos um dos operandos seja do tipo que define a sobrecarga.

✔️ O DO sobrecarrega os operadores de forma simétrica.

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

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

Muitos idiomas não suportam sobrecarga do operador. Por esse motivo, recomenda-se que os tipos que sobrecarregam os operadores incluam um método secundário com um nome específico de domínio apropriado que forneça funcionalidade equivalente.

A tabela a seguir contém uma lista de operadores e os nomes de métodos 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 ==

A sobrecarga operator == é bastante complicada. 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. Existem dois tipos de operadores de conversão: implícitos e explícitos.

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

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

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

❌ NÃO forneça um operador de conversão implícito se a conversão for potencialmente com perdas.

Por exemplo, não deve haver uma conversão implícita de Double para Int32 porque Double tem uma gama mais ampla do que Int32. Pode ser fornecido um operador de conversão explícito mesmo que a conversão seja potencialmente deficitária.

❌ NÃO lance exceções de moldes implícitos.

É muito difícil para os usuários finais entender o que está acontecendo, porque eles podem não estar cientes de que uma conversão está ocorrendo.

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

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

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

Consulte também