Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A felhasználó által definiált típus túlterhelhet egy előre definiált C# operátort. Ez azt jelzi, hogy egy típus lehetővé teheti egy művelet egyéni implementálását abban az esetben, ha az egyik vagy mindkét operandus ilyen típusú. A Túlterhelhető operátorok szakasz azt mutatja be, hogy mely C#-operátorok terhelhetők túl.
operator A kulcsszó használatával deklarálhat egy operátort. Az operátor-deklarációnak meg kell felelnie a következő szabályoknak:
- Ez tartalmaz egy
publicmódosító. - A nem kötelező operátorok egyetlen bemeneti paraméterrel rendelkeznek. A bináris operátor két bemeneti paraméterrel rendelkezik. Minden esetben legalább egy paraméternek típusú
TvagyT?kell lennie, aholTaz operátor deklarációt tartalmazó típus. - Tartalmazza a
staticmódosító, kivéve az összetett hozzárendelési operátorok, például+=. - Az inkrement (
++) és dekrement (--) operátorok statikus vagy példánymetódusként is implementálhatók. A példánymetódus-operátorok a C# 14-ben bevezetett új funkciók.
Az alábbi példa egy egyszerűsített struktúrát határoz meg, amely egy racionális számot jelöl. A struktúra túlterheli az aritmetikai operátorok némelyikét:
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
}
}
Az előző példát kiterjesztheti úgy, hogy implicit konverziót határoz megint-ről Fraction-re. Ezután a túlterhelt operátorok támogatnák a két típus argumentumait. Ez azt jelenti, hogy egy egész számot adhat hozzá egy törthöz, és ennek eredményeként egy törtet kaphat.
A kulcsszóval operator egyéni típuskonvertálást is definiálhat. További információ: Felhasználó által definiált konverziós operátorok.
Túlterhelhető operátorok
Az alábbi táblázat a túlterhelhető operátorokat mutatja be:
| Működtetők | Jegyzetek |
|---|---|
+x, -x, !x, ~x++, --, truefalse |
Az true és false operátort együtt kell túlterhelni. |
x + y, x - y, x * y, x / yx % yx & y, x | y, x ^ y\ |
|
x == y, x != y, x < y, x > yx <= yx >= y |
A következő párokban kell túlterhelni: == és !=, < és >, <= és >=. |
+=, -=, *=, /=, %=&=, \|=, ^=, <<=, , >>=>>>= |
Az összetett hozzárendelési operátorok túlterhelhetők a C# 14-ben és újabb verzióiban. |
Az összetett hozzárendelés túlterhelt operátorának az alábbi szabályokat kell követnie:
- A módosítónak
publictartalmaznia kell. - Nem tartalmazhatja a
staticmódosítót. - A visszatérési típusnak meg kell lennie
void. - A deklarációnak tartalmaznia kell egy paramétert, amely az összetett hozzárendelés jobb oldalát jelöli.
A C# 14 verziótól kezdve a növekmény- és csökkenésoperátorok példánytagokként túlterhelhetők. A példány-operátorok az új példányok létrehozásának elkerülésével növelhetik a teljesítményt. A példányoperátornak a következő szabályokat kell követnie:
- A módosítónak
publictartalmaznia kell. - Nem tartalmazhatja a
staticmódosítót. - A visszatérési típusnak meg kell lennie
void. - Nem deklarálhat paramétereket, még akkor sem, ha ezek a paraméterek alapértelmezett értékkel rendelkeznek.
Nem túlterhelhető operátorok
Az alábbi táblázat azokat az operátorokat mutatja be, amelyek nem terhelhetők túl:
| Működtetők | Alternatívák |
|---|---|
x && y, x || y |
Túlterhelje mind az true operátorokat false , mind az & operátorokat | . További információ: Felhasználó által definiált feltételes logikai operátorok. |
a[i], a?[i] |
Indexelő definiálása. |
(T)x |
Egyéni típuskonverziók definiálása, amelyeket egy öntött kifejezés hajt végre. További információ: Felhasználó által definiált konverziós operátorok. |
^x, x = y, x.y, x?.yc ? t : f, x ?? y, ??= yx..y, x->y, =>, f(x), as, await, checked, unchecked, default, delegate, is, nameof, new,sizeof, stackalloc, switch, typeofwith |
Nincs. |
A C# 14 előtt az összetett operátorok nem terhelhetők túl. A megfelelő bináris operátor túlterhelése implicit módon túlterheli a megfelelő összetett hozzárendelési operátort.
Operátorok túlterhelésének feloldása
Fontos
Ez a szakasz a C# 14-es és újabb verzióira vonatkozik. C# 14 előtt a felhasználó által definiált összetett hozzárendelési operátorok, valamint a példány növekményes és csökkentő operátorok nem engedélyezettek.
Ha x változóként van besorolva egy összetett hozzárendelési kifejezésben, például x «op»= y, akkor a statikus operátorokkal szemben a példány-operátorok kapnak előnyt «op» esetében. Ha egy túlterhelt «op»= operátor nincs deklarálva a változó típusához x , vagy x nincs besorolva változóként, akkor a statikus operátorokat használja a rendszer.
Ha a postfix operátor ++x nem változóként van besorolva, vagy a kifejezést x++ használja, a rendszer figyelmen kívül hagyja a példánytoperator++. Ellenkező esetben a rendszer előnyben részesíti a példányt operator ++. Például
x++; // Instance operator++ preferred.
y = x++; // instance operator++ isn't considered.
Ennek a szabálynak az az oka, hogy y értékét xelőtt kell hozzárendelni, hogy az növelve legyen. A fordító nem tudja meghatározni, hogy egy felhasználó által meghatározott implementáció esetében referenciatípusban van-e.
Az előtag operátora ++ esetében, ha x változóként van besorolva ++x-ben, a példányoperátort előnyben részesítik a statikus unáris operátorral szemben.
C# nyelvspecifikáció
További információt a C# nyelvspecifikációjának alábbi szakaszaiban talál: