Перегрузки операторовOperator Overloads

Перегрузки оператора позволяют типам фреймворков отображаться так, как если бы они были встроенными примитивами языка.Operator overloads allow framework types to appear as if they were built-in language primitives.

Хотя это допустимо и полезно в некоторых ситуациях, оператор перегрузки должны использоваться осторожно.Although allowed and useful in some situations, operator overloads should be used cautiously. Есть много случаев, когда перегрузка оператора была злоупотреблять, например, когда конструкторы фреймворков начали использовать операторов для операций, которые должны быть простыми методами.There are many cases in which operator overloading has been abused, such as when framework designers started to use operators for operations that should be simple methods. Следующие рекомендации должны помочь вам решить, когда и как использовать перегрузку оператора.The following guidelines should help you decide when and how to use operator overloading.

❌AVOID определяет перегрузки оператора, за исключением типов, которые должны чувствовать себя примитивными (встроенными) типами.❌ AVOID defining operator overloads, except in types that should feel like primitive (built-in) types.

✔️ CONSIDER, определяющий перегрузки оператора в типе, который должен чувствовать себя примитивным типом.✔️ CONSIDER defining operator overloads in a type that should feel like a primitive type.

Например, System.String operator== имеет operator!= и определяется.For example, System.String has operator== and operator!= defined.

✔️ DO определяют перегрузки оператора в структурках, представляющих числа System.Decimal(например,).✔️ DO define operator overloads in structs that represent numbers (such as System.Decimal).

❌НЕ быть милопри определяя перегрузки оператора.❌ DO NOT be cute when defining operator overloads.

Перегрузка оператора полезна в тех случаях, когда сразу становится ясно, каким будет результат операции.Operator overloading is useful in cases in which it is immediately obvious what the result of the operation will be. Например, имеет смысл, чтобы иметь DateTime возможность DateTime вычесть TimeSpanодин из другого и получить .For example, it makes sense to be able to subtract one DateTime from another DateTime and get a TimeSpan. Однако нецелесообразно использовать оператора логического союза для объединения двух запросов базы данных или для записи оператора смены в поток.However, it is not appropriate to use the logical union operator to union two database queries, or to use the shift operator to write to a stream.

❌НЕ предоставляйте оператору перегрузки, если по крайней мере один из operands не имеет типа, определяющего перегрузку.❌ DO NOT provide operator overloads unless at least one of the operands is of the type defining the overload.

✔️ перегрузки операторов симметричным образом.✔️ DO overload operators in a symmetric fashion.

Например, если вы operator==перегружаете, operator!=вы также должны перегрузить .For example, if you overload the operator==, you should also overload the operator!=. Аналогичным образом, если operator<вы перегружаете operator>, вы также должны перегрузить , и так далее.Similarly, if you overload the operator<, you should also overload the operator>, and so on.

✔️ CONSIDER предоставляет методы с дружественными именами, которые соответствуют каждому перегруженного оператора.✔️ CONSIDER providing methods with friendly names that correspond to each overloaded operator.

Многие языки не поддерживают перегрузку оператора.Many languages do not support operator overloading. По этой причине рекомендуется, чтобы типы, перегружающие операторов, включали вторичный метод с соответствующим доменным именем, обеспечивающим эквивалентную функциональность.For this reason, it is recommended that types that overload operators include a secondary method with an appropriate domain-specific name that provides equivalent functionality.

Следующая таблица содержит список операторов и соответствующие имена дружественных методов.The following table contains a list of operators and the corresponding friendly method names.

Символ оператора СЗC# Operator Symbol Имя метаданныхMetadata Name Понятное имяFriendly Name
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

Оператор перегрузкиOverloading Operator ==

Перегрузка operator == довольно сложна.Overloading operator == is quite complicated. Семантика оператора должна быть совместима с несколькими Object.Equalsдругими участниками, такими как .The semantics of the operator need to be compatible with several other members, such as Object.Equals.

Операторы преобразованияConversion Operators

Операторы конверсии являются неопроизвонелыми операторами, которые позволяют конверсировать из одного типа в другой.Conversion operators are unary operators that allow conversion from one type to another. Операторы должны быть определены как статические члены либо на операнде, либо на типе возврата.The operators must be defined as static members on either the operand or the return type. Существует два типа операторов конверсий: неявный и явный.There are two types of conversion operators: implicit and explicit.

❌НЕ предоставляйте оператора конверсии, если такое преобразование явно не ожидается конечными пользователями.❌ DO NOT provide a conversion operator if such conversion is not clearly expected by the end users.

❌НЕ определяйте операторов конверсии за пределами домена типа.❌ DO NOT define conversion operators outside of a type’s domain.

Например, Int32 Double, Decimal и все численные типы, в то время как DateTime нет.For example, Int32, Double, and Decimal are all numeric types, whereas DateTime is not. Таким образом, не должно быть Double(long) оператора DateTimeпреобразования для преобразования в .Therefore, there should be no conversion operator to convert a Double(long) to a DateTime. В таком случае предпочтительнее конструктор.A constructor is preferred in such a case.

❌НЕ предоставляйте оператора неявного преобразования, если преобразование потенциально убыточно.❌ DO NOT provide an implicit conversion operator if the conversion is potentially lossy.

Например, не должно быть неявного преобразования от Double к потому, Int32 что Double имеет более широкий диапазон, чем Int32.For example, there should not be an implicit conversion from Double to Int32 because Double has a wider range than Int32. Оператор явного преобразования может быть предоставлен, даже если конверсия потенциально убыточна.An explicit conversion operator can be provided even if the conversion is potentially lossy.

❌НЕ выбрасывайте исключения из неявных слепков.❌ DO NOT throw exceptions from implicit casts.

Конечным пользователям очень трудно понять, что происходит, потому что они могут не знать, что происходит преобразование.It is very difficult for end users to understand what is happening, because they might not be aware that a conversion is taking place.

✔️ DO System.InvalidCastException throw, если вызов литой оператора приводит к убыточной конверсии и договор оператора не позволяет убыточные преобразования.✔️ DO throw System.InvalidCastException if a call to a cast operator results in a lossy conversion and the contract of the operator does not allow lossy conversions.

Порции © 2005, 2009 Microsoft Corporation. Все права зарезервированы.Portions © 2005, 2009 Microsoft Corporation. All rights reserved.

Перепечатано с разрешения Pearson Education, Inc. из книги Инфраструктура программных проектов. Соглашения, идиомы и шаблоны для многократно используемых библиотек .NET (2-е издание), авторы: Кржиштоф Цвалина (Krzysztof Cwalina) и Брэд Абрамс (Brad Abrams). Книга опубликована 22 октября 2008 г. издательством Addison-Wesley Professional в рамках серии, посвященной разработке для Microsoft Windows.Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, published Oct 22, 2008 by Addison-Wesley Professional as part of the Microsoft Windows Development Series.

См. также разделSee also