Överlagring av operatorer
Kommentar
Det här innehållet skrivs om med behörighet från Pearson Education, Inc. från Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Den utgåvan publicerades 2008, och boken har sedan dess reviderats helt i den tredje utgåvan. En del av informationen på den här sidan kan vara inaktuell.
Med överlagringar av operatorer kan ramverkstyper visas som om de vore inbyggda språkprimitatorer.
Även om det är tillåtet och användbart i vissa situationer bör operatoröverlagringar användas försiktigt. Det finns många fall där överbelastning av operatören har missbrukats, till exempel när ramverksdesigners började använda operatorer för åtgärder som borde vara enkla metoder. Följande riktlinjer bör hjälpa dig att bestämma när och hur du ska använda operatörsöverlagring.
❌ UNDVIK att definiera operatoröverlagringar, förutom i typer som ska kännas som primitiva (inbyggda) typer.
✔️ ÖVERVÄG att definiera operatoröverlagringar i en typ som ska kännas som en primitiv typ.
Till System.String exempel har operator==
och operator!=
definierat.
✔️ DEFINIERA operatoröverlagringar i structs som representerar tal (till exempel System.Decimal).
❌ VAR INTE söt när du definierar operatörsöverbelastningar.
Operatörsöverlagring är användbart i de fall då det är uppenbart direkt vad resultatet av åtgärden kommer att bli. Det är till exempel vettigt att kunna subtrahera en från en DateTime annan DateTime
och få en TimeSpan. Det är dock inte lämpligt att använda den logiska unionsoperatorn för att unionera två databasfrågor, eller att använda skiftoperatorn för att skriva till en dataström.
❌ Ange INTE operatoröverlagringar om inte minst en av operanderna är av den typ som definierar överbelastningen.
✔️ Överlagrar operatorer på ett symmetriskt sätt.
Om du till exempel överbelastar operator==
bör du även överbelasta operator!=
. På samma sätt, om du överbelastar operator<
, bör du också överbelasta operator>
, och så vidare.
✔️ ÖVERVÄG att tillhandahålla metoder med egna namn som motsvarar varje överbelastad operator.
Många språk stöder inte överlagring av operatorer. Därför rekommenderar vi att typer som överbelastar operatorer inkluderar en sekundär metod med ett lämpligt domänspecifikt namn som ger motsvarande funktioner.
Följande tabell innehåller en lista över operatorer och motsvarande egna metodnamn.
C#-operatorsymbol | Metadatanamn | Eget namn |
---|---|---|
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 |
Överlagringsoperator ==
operator ==
Överlagring är ganska komplicerat. Operatorns semantik måste vara kompatibel med flera andra medlemmar, till exempel Object.Equals.
Konverteringsoperatorer
Konverteringsoperatorer är unary-operatorer som tillåter konvertering från en typ till en annan. Operatorerna måste definieras som statiska medlemmar på antingen operanden eller returtypen. Det finns två typer av konverteringsoperatorer: implicita och explicita.
❌ Ange INTE en konverteringsoperator om en sådan konvertering inte klart förväntas av slutanvändarna.
❌ Definiera INTE konverteringsoperatorer utanför en typs domän.
Till exempel Int32, , och Decimal är alla numeriska typer, medan DateTime det Doubleinte är det. Därför bör det inte finnas någon konverteringsoperator för att konvertera en Double(long)
till en DateTime
. En konstruktor föredras i ett sådant fall.
❌ Ange INTE en implicit konverteringsoperator om konverteringen kan vara förlust.
Det bör till exempel inte finnas någon implicit konvertering från Double
till Int32
eftersom Double
har ett bredare intervall än Int32
. En explicit konverteringsoperator kan tillhandahållas även om konverteringen kan vara förlust.
❌ Kasta INTE undantag från implicita casts.
Det är mycket svårt för slutanvändarna att förstå vad som händer, eftersom de kanske inte är medvetna om att en konvertering pågår.
✔️ System.InvalidCastException Kasta om ett anrop till en cast-operator resulterar i en förlustkonvertering och operatörens kontrakt inte tillåter förlustkonverteringar.
Portioner © 2005, 2009 Microsoft Corporation. Med ensamrätt.
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, publicerad 22 okt 2008 av Addison-Wesley Professional som en del av Microsoft Windows Development Series.