Share via


Ö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.

Se även