Przeciążenia operatorów

Uwaga

Ta zawartość jest drukowana przez uprawnienie Pearson Education, Inc. z Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Wydanie to zostało opublikowane w 2008 roku, a książka została w pełni zmieniona w trzecim wydaniu. Niektóre informacje na tej stronie mogą być nieaktualne.

Przeciążenia operatorów umożliwiają pojawienie się typów struktur tak, jakby były wbudowanymi elementami pierwotnymi języka.

Mimo że dozwolone i przydatne w niektórych sytuacjach, przeciążenia operatorów powinny być używane ostrożnie. Istnieje wiele przypadków, w których przeciążenie operatora zostało nadużywane, na przykład gdy projektanci struktur zaczęli używać operatorów do operacji, które powinny być prostymi metodami. Poniższe wskazówki powinny pomóc w podjęciu decyzji o tym, kiedy i jak używać przeciążenia operatora.

❌ UNIKAJ definiowania przeciążeń operatorów, z wyjątkiem typów, które powinny wyglądać jak typy pierwotne (wbudowane).

✔️ ROZWAŻ zdefiniowanie przeciążeń operatorów w typie, który powinien wyglądać jak typ pierwotny.

Na przykład System.String ma operator== i operator!= zdefiniowano.

✔️ Do define operator przeciążenia w strukturach reprezentujących liczby (na przykład System.Decimal).

❌ Nie należy stosować cięć podczas definiowania przeciążeń operatorów.

Przeciążenie operatora jest przydatne w przypadkach, w których natychmiast jest oczywiste, jaki będzie wynik operacji. Na przykład warto odjąć jeden DateTime od innego DateTime i uzyskać wartość TimeSpan. Jednak nie jest właściwe użycie operatora unii logicznej do utworzenia dwóch zapytań bazy danych lub użycie operatora shift do zapisu w strumieniu.

❌ NIE należy dostarczać przeciążeń operatorów, chyba że co najmniej jeden z operandów jest typu definiującego przeciążenie.

✔️ Operatory przeciążenia DO w sposób symetryczny.

Jeśli na przykład przeciążysz element operator==, należy również przeciążyć element operator!=. Podobnie, jeśli przeciążysz operator<element , należy również przeciążyć operator>element i tak dalej.

✔️ ROZWAŻ podanie metod z przyjaznymi nazwami odpowiadającymi każdemu przeciążonemu operatorowi.

Wiele języków nie obsługuje przeciążenia operatora. Z tego powodu zaleca się, aby typy, które przeciążyły operatory, obejmują metodę pomocniczą z odpowiednią nazwą specyficzną dla domeny, która zapewnia równoważne funkcje.

Poniższa tabela zawiera listę operatorów i odpowiednie przyjazne nazwy metod.

Symbol operatora języka C# Nazwa metadanych Przyjazna nazwa
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

Operator przeciążenia ==

Przeciążenie operator == jest dość skomplikowane. Semantyka operatora musi być zgodna z kilkoma innymi elementami członkowskimi, takimi jak Object.Equals.

Operatory konwersji

Operatory konwersji to operatory jednoargumentowe, które umożliwiają konwersję z jednego typu na inny. Operatory muszą być zdefiniowane jako statyczne elementy członkowskie w operand lub zwracany typ. Istnieją dwa typy operatorów konwersji: niejawne i jawne.

❌ Nie udostępniaj operatora konwersji, jeśli taka konwersja nie jest wyraźnie oczekiwana przez użytkowników końcowych.

❌ NIE należy definiować operatorów konwersji poza domeną typu.

Na przykład , Int32Doublei Decimal są wszystkimi typami liczbowymi, natomiast DateTime nie jest. W związku z tym nie powinien istnieć operator konwersji, aby przekonwertować Double(long) element na DateTime. Konstruktor jest preferowany w takim przypadku.

❌ Nie należy podawać niejawnego operatora konwersji, jeśli konwersja jest potencjalnie strata.

Na przykład nie powinno istnieć niejawna konwersja z Double do Int32 , ponieważ Double ma szerszy zakres niż Int32. Można podać jawny operator konwersji, nawet jeśli konwersja jest potencjalnie strata.

❌ NIE zgłaszaj wyjątków od niejawnych rzutów.

Użytkownikom końcowym bardzo trudno jest zrozumieć, co się dzieje, ponieważ mogą nie być świadomi, że odbywa się konwersja.

✔️ Wyrzuć, System.InvalidCastException jeśli wywołanie operatora rzutowania powoduje utratę konwersji, a kontrakt operatora nie zezwala na konwersje strat.

© Części 2005, 2009 Microsoft Corporation. Wszelkie prawa zastrzeżone.

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 w ramach Microsoft Windows Development Series.

Zobacz też