Dela via


Operatoröverbelastning

Anmärkning

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 överbelastning av operatorer användas försiktigt. Det finns många fall där operatoröverbelastning har missbrukats, till exempel när ramverksutvecklare började använda operatorer för operationer som bör vara enkla metoder. Följande riktlinjer ska hjälpa dig att avgöra hur och när du bör 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.

Exempelvis har System.Stringoperator== och operator!= definierade.

✔️ DEFINIERA operatoröverlagringar i strukturer 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 DateTime från en 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 överlagringen.

✔️ Du bör överlagra 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 vänliga namn som motsvarar varje överbelastad operator.

Många språk stöder inte operatoröverlagring. 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 Vänligt 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 == Överbelastning ä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 är Int32, Double, och Decimal alla numeriska typer, medan DateTime inte ä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 vid implicita typomvandlingar.

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. Alla rättigheter reserverade.

Återtryckt med tillstånd från Pearson Education, Inc. från Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition av Krzysztof Cwalina och Brad Abrams, publicerades den 22 oktober 2008 av Addison-Wesley Professional som en del av Microsoft Windows Development Series.

Se även