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
public
wijzigingsfunctie. - Een unaire operator heeft één invoerparameter. Een binaire operator heeft twee invoerparameters. In elk geval moet ten minste één parameter een type
T
hebben ofT?
waarT
het type is dat de operatordeclaratie bevat. - Het omvat de
static
modificator, met uitzondering van de samengestelde toewijzingsoperatoren, zoals+=
. - De operatoren voor incrementele (
++
) en decrement (--
) kunnen worden geïmplementeerd als statische of instantiemethoden.
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++, operand.denominator);
public static Fraction operator --(Fraction operand) =>
new Fraction(operand.numerator--, 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 , , ++ , , -- true false |
De true en false operatoren moeten samen worden overladen. |
x + y , x - y , x * y , x / y , x % y x & y , x | y , x ^ y x << y , , x >> y x >>> y |
|
x == y , , x != y x < y , x > y , , , x <= y x >= 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
public
wijzigingsfunctie bevatten. - De
static
modificator 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
public
wijzigingsfunctie bevatten. - De
static
modificator 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 = y x.y , x?.y , , c ? t : f , , x ?? y ??= y x..y , x->y , => , f(x) , as , await , checked , unchecked , default , delegate , is , nameof , new ,sizeof
stackalloc , switch , typeof with |
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 x
x
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 x
voordat 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: