Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Uživatelem definovaný typ může přetížit předdefinovaný operátor jazyka C#. To znamená, že typ může poskytnout vlastní implementaci operace v případě, že jeden nebo oba operandy jsou tohoto typu. Oddíl Přetížitelné operátory ukazuje, které operátory jazyka C# je možné přetížit.
Deklarujte operátor pomocí klíčového slova operator. Deklarace operátoru musí splňovat následující pravidla:
-
publicObsahuje modifikátor. - Unární operátor má jeden vstupní parametr. Binární operátor má dva vstupní parametry. V každém případě musí mít alespoň jeden parametr typ
TneboT?kdeTje typ, který obsahuje deklaraci operátoru. -
staticObsahuje modifikátor s výjimkou operátorů složeného přiřazení, například+=. - Operátory inkrementace () a dekrementace (
++--) je možné implementovat jako statické metody nebo metody instance. Operátory metod instancí jsou novou funkcí zavedenou v jazyce C# 14.
Následující příklad definuje zjednodušenou strukturu, která představuje logické číslo. Struktura přetíží některé aritmetické operátory:
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
}
}
Předchozí příklad můžete rozšířit definováním implicitního převodu z int na Fraction. Přetížené operátory by pak podporovaly argumenty těchto dvou typů. To znamená, že by bylo možné přidat celé číslo k zlomku a získat zlomek v důsledku toho.
Pomocí klíčového slova operator definujete převod vlastního typu. Další informace naleznete v tématu Uživatelem definované operátory převodu.
Přetížitelné operátory
Následující tabulka ukazuje operátory, které je možné přetížit:
| Operátoři | Poznámky |
|---|---|
+x, -x, !x, , ~x++, --, , truefalse |
Operátory true a false musí být přetíženy dohromady. |
x + y, x - y, x * y, x / y, , x % yx & y, x | y, , x ^ yx << y, , x >> yx >>> y |
|
x == y, x != y, x < y, x > y, , x <= yx >= y |
Musí být přetíženy ve dvojicích následujícím způsobem: == a !=< , a ><= , a >=. |
+=, -=, , *=, /=%=&=\|=^=<<=, >>=>>>= |
Operátory složeného přiřazení je možné přetížit v jazyce C# 14 a novějším. |
Přetížený operátor složeného přiřazení musí dodržovat tato pravidla:
- Musí obsahovat
publicmodifikátor. - Modifikátor nemůže obsahovat
static. - Návratový typ musí být
void. - Deklarace musí obsahovat jeden parametr, který představuje pravou stranu složeného přiřazení.
Počínaje jazykem C# 14 je možné přetížit operátory inkrementace (++) a dekrementace (--) jako členy instance. Operátory instancí můžou zvýšit výkon tím, že se zabrání vytvoření nové instance. Operátor instance musí dodržovat tato pravidla:
- Musí obsahovat
publicmodifikátor. - Modifikátor nemůže obsahovat
static. - Návratový typ musí být
void. - Nemůže deklarovat žádné parametry, i když mají tyto parametry výchozí hodnotu.
Nepřetížitelné operátory
Následující tabulka ukazuje operátory, které nelze přetížit:
| Operátoři | Alternativy |
|---|---|
x && y, x || y |
Přetěžujte jak operátory true a false, tak operátory & nebo |. Další informace naleznete v tématu Uživatelem definované podmíněné logické operátory. |
a[i], a?[i] |
Definujte indexer. |
(T)x |
Definujte vlastní převody typů prováděné výrazem typu. Další informace naleznete v tématu Uživatelem definované operátory převodu. |
^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, newsizeof, stackalloc, switch, , typeofwith |
Žádné. |
Před C# 14 nelze složené operátory přetížit. Přetížení odpovídajícího binárního operátoru implicitně přetěžuje odpovídající operátor složeného přiřazení.
Rozlišení přetížení operátoru
Důležité
Tato část platí pro C# 14 a novější. Před verzí C# 14 nejsou povolené operátory pro uživatelem definované složené přiřazení a operátory pro inkrementaci a dekrementaci instancí.
Pokud je x klasifikován jako proměnná ve výrazu složeného přiřazení, jako je například x «op»= y, mají instance operátorů přednost před libovolným statickým operátorem pro «op». Pokud není přetížený «op»= operátor deklarován pro typ x proměnné nebo x není klasifikován jako proměnná, použijí se statické operátory.
Pro postfixový operátor ++, pokud x není klasifikováno jako proměnná nebo je použit výraz x++, instance operator++ je ignorována. V opačném případě je upřednostněná instance operator ++. Příklad:
x++; // Instance operator++ preferred.
y = x++; // instance operator++ isn't considered.
Důvodem tohoto pravidla je, že y by se měla přiřadit k hodnotě xpřed jejím zvýšením. Kompilátor nedokáže určit podmínky pro uživatelsky definovanou implementaci v referenčním typu.
U operátoru předpony ++, pokud je x klasifikován jako proměnná v ++x, je preferován operátor instance před statickým unárním operátorem.
Specifikace jazyka C#
Další informace najdete v následujících částech specifikace jazyka C#: