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:
-
public
Obsahuje 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
T
neboT?
kdeT
je typ, který obsahuje deklaraci operátoru. -
static
Obsahuje 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.
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++, 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
}
}
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 ++ , -- , , true false |
Operátory true a false musí být přetíženy dohromady. |
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 |
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
public
modifiká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
public
modifiká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?.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 |
Žá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ě x
př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#: