Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Een door de gebruiker gedefinieerd type kan een vooraf gedefinieerde C#-operator overbelasten. Dat wil gezegd, een type kan de aangepaste implementatie van een bewerking bieden voor het geval een of beide operanden van dat type zijn. In de sectie Overbelastingsbare operators ziet u welke C#-operators kunnen worden overbelast.
Gebruik het operator trefwoord om een operator te declareren. Een operatordeclaratie moet voldoen aan de volgende regels:
- Het bevat een
publicwijzigingsfunctie. - Een unaire operator heeft één invoerparameter. Een binaire operator heeft twee invoerparameters. In elk geval moet ten minste één parameter een type
Thebben ofT?waarThet type is dat de operatordeclaratie bevat. - Het omvat de
staticmodificator, met uitzondering van de samengestelde toewijzingsoperatoren, zoals+=. - De operatoren voor incrementele (
++) en decrement (--) kunnen worden geïmplementeerd als statische of instantiemethoden. Operatoren voor exemplaarmethoden zijn een nieuwe functie die is geïntroduceerd in C# 14.
In het volgende voorbeeld wordt een vereenvoudigde structuur gedefinieerd die een rationeel getal vertegenwoordigt. De structuur overbelast enkele rekenkundige operatoren:
public struct Fraction
{
private int numerator;
private int denominator;
public Fraction(int numerator, int denominator)
{
if (denominator == 0)
{
throw new ArgumentException("Denominator cannot be zero.", nameof(denominator));
}
this.numerator = numerator;
this.denominator = denominator;
}
public static Fraction operator +(Fraction operand) => operand;
public static Fraction operator -(Fraction operand) => new Fraction(-operand.numerator, operand.denominator);
public static Fraction operator +(Fraction left, Fraction right)
=> new Fraction(left.numerator * right.denominator + right.numerator * left.denominator, left.denominator * right.denominator);
public static Fraction operator -(Fraction left, Fraction right)
=> left + (-right);
public static Fraction operator *(Fraction left, Fraction right)
=> new Fraction(left.numerator * right.numerator, left.denominator * right.denominator);
public static Fraction operator /(Fraction left, Fraction right)
{
if (right.numerator == 0)
{
throw new DivideByZeroException();
}
return new Fraction(left.numerator * right.denominator, left.denominator * right.numerator);
}
// Define increment and decrement to add 1/den, rather than 1/1.
public static Fraction operator ++(Fraction operand)
=> new Fraction(operand.numerator + 1, operand.denominator);
public static Fraction operator --(Fraction operand) =>
new Fraction(operand.numerator - 1, operand.denominator);
public override string ToString() => $"{numerator} / {denominator}";
// New operators allowed in C# 14:
public void operator +=(Fraction operand) =>
(numerator, denominator ) =
(
numerator * operand.denominator + operand.numerator * denominator,
denominator * operand.denominator
);
public void operator -=(Fraction operand) =>
(numerator, denominator) =
(
numerator * operand.denominator - operand.numerator * denominator,
denominator * operand.denominator
);
public void operator *=(Fraction operand) =>
(numerator, denominator) =
(
numerator * operand.numerator,
denominator * operand.denominator
);
public void operator /=(Fraction operand)
{
if (operand.numerator == 0)
{
throw new DivideByZeroException();
}
(numerator, denominator) =
(
numerator * operand.denominator,
denominator * operand.numerator
);
}
public void operator ++() => numerator++;
public void operator --() => numerator--;
}
public static class OperatorOverloading
{
public static void Main()
{
var a = new Fraction(5, 4);
var b = new Fraction(1, 2);
Console.WriteLine(-a); // output: -5 / 4
Console.WriteLine(a + b); // output: 14 / 8
Console.WriteLine(a - b); // output: 6 / 8
Console.WriteLine(a * b); // output: 5 / 8
Console.WriteLine(a / b); // output: 10 / 4
}
}
U kunt het voorgaande voorbeeld uitbreiden door een impliciete conversie van int naar Fraction. Vervolgens ondersteunen overbelaste operators argumenten van deze twee typen. Dat wil zeggen, het zou mogelijk zijn om een geheel getal toe te voegen aan een breuk en een breuk als resultaat te verkrijgen.
Je gebruikt ook het operator trefwoord om een conversie van aangepaste typen te definiëren. Zie Door de gebruiker gedefinieerde conversieoperators voor meer informatie.
Overbelastingsoperators
In de volgende tabel ziet u de operators die kunnen worden overbelast:
| Bedieners | Opmerkingen |
|---|---|
+x, , -x!x, ~x, , ++, , --truefalse |
De true en false operatoren moeten samen worden overladen. |
x + y, x - y, x * y, x / y, x % yx & y, x | y, x ^ yx << y, , x >> yx >>> y |
|
x == y, , x != yx < y, x > y, , , x <= yx >= y |
Moet als volgt in paren worden overbelast: == en !=, < en >, <= en >=. |
+=, , -=*=, /=, %=, , &=, , \|=^=<<=>>=>>>= |
In C# 14 en hoger kunnen de operators voor samengestelde toewijzingen worden overbelast. |
Een overbelaste operator voor samengestelde toewijzing moet de volgende regels volgen:
- Deze moet de
publicwijzigingsfunctie bevatten. - De
staticmodificator kan niet worden opgenomen. - Het retourtype moet zijn
void. - De declaratie moet één parameter bevatten, die de rechterkant van de samengestelde toewijzing aangeeft.
Vanaf C# 14 kunnen de operatoren voor verhoging (++) en verlagen (--) worden overbelast als instantiemembers. Exemplaaroperators kunnen de prestaties verbeteren door het maken van een nieuw exemplaar te voorkomen. Een exemplaaroperator moet de volgende regels volgen:
- Deze moet de
publicwijzigingsfunctie bevatten. - De
staticmodificator kan niet worden opgenomen. - Het retourtype moet zijn
void. - Er kunnen geen parameters worden declareren, zelfs niet als deze parameters een standaardwaarde hebben.
Niet-overbelaste operators
In de volgende tabel ziet u de operators die niet kunnen worden overbelast:
| Bedieners | Alternatieven |
|---|---|
x && y, x || y |
Overbelast zowel de true en false operatoren als de & en | operatoren. Zie Door de gebruiker gedefinieerde logische operators voor meer informatie. |
a[i], a?[i] |
Definieer een indexeerder. |
(T)x |
Definieer aangepaste typeconversies die worden uitgevoerd door een cast-expressie. Zie Door de gebruiker gedefinieerde conversieoperators voor meer informatie. |
^x, , x = yx.y, x?.y, , c ? t : f, , x ?? y??= yx..y, x->y, =>, f(x), as, await, checked, unchecked, default, delegate, is, nameof, new,sizeof
stackalloc, switch, typeofwith |
Geen. |
Voor C# 14 kunnen de samengestelde operators niet worden overbelast. Door de bijbehorende binaire operator te overbelasten, wordt de bijbehorende operator voor samengestelde toewijzing impliciet overbelast.
Oplossing van overbelasting van operator
Belangrijk
Deze sectie is van toepassing op C# 14 en hoger. Vóór C# 14 zijn gebruikersgedefinieerde samengestelde toewijzingsoperatoren en incrementele en decrementoperatoren voor exemplaren niet toegestaan.
Als x wordt geclassificeerd als een variabele in een samengestelde toewijzingsexpressie zoals x «op»= y, hebben de instantieoperators de voorkeur boven een statische operator voor «op». Als een overbelaste «op»= operator niet is gedeclareerd voor het type of xx niet als variabele wordt geclassificeerd, worden de statische operators gebruikt.
Als de postfix-operator ++x niet is geclassificeerd als een variabele of als de expressie x++ wordt gebruikt, wordt het exemplaar operator++ genegeerd. Anders wordt de voorkeur gegeven aan het exemplaar operator ++. Bijvoorbeeld
x++; // Instance operator++ preferred.
y = x++; // instance operator++ isn't considered.
De reden voor deze regel is dat y moet worden toegewezen aan de waarde van xvoordat deze wordt verhoogd. De compiler kan niet bepalen dat voor een door de gebruiker gedefinieerde implementatie in een referentietype.
Voor de voorvoegseloperator ++, als x in ++x is geclassificeerd als een variabele, heeft de instantieoperator de voorkeur boven een statische unaire operator.
C#-taalspecificatie
Zie de volgende secties van de C#-taalspecificatie voor meer informatie: