Перегрузка операторов — предопределенные унарные, арифметические операторы, операторы равенства и сравнения
Определяемый пользователем тип может перегружать предопределенный оператор C#. То есть тип может указать пользовательскую реализацию операции, если один или оба операнда принадлежат этому типу. В разделе Перегружаемые операторы показано, какие операторы C# можно перегружать.
Для объявления оператора используйте ключевое слово operator
. Объявление оператора должно соответствовать следующим правилам:
- Оно должно включать
public
и модификаторstatic
. - У унарного оператора один входной параметр. У бинарного оператора два входных параметра. В каждом случае хотя бы один параметр должен иметь тип
T
илиT?
, гдеT
— тип, который содержит объявление оператора.
В следующем примере определяется упрощенная структура, представляющая рациональное число. Структура перегружает некоторые арифметические операторы:
public readonly struct Fraction
{
private readonly int num;
private readonly int den;
public Fraction(int numerator, int denominator)
{
if (denominator == 0)
{
throw new ArgumentException("Denominator cannot be zero.", nameof(denominator));
}
num = numerator;
den = denominator;
}
public static Fraction operator +(Fraction a) => a;
public static Fraction operator -(Fraction a) => new Fraction(-a.num, a.den);
public static Fraction operator +(Fraction a, Fraction b)
=> new Fraction(a.num * b.den + b.num * a.den, a.den * b.den);
public static Fraction operator -(Fraction a, Fraction b)
=> a + (-b);
public static Fraction operator *(Fraction a, Fraction b)
=> new Fraction(a.num * b.num, a.den * b.den);
public static Fraction operator /(Fraction a, Fraction b)
{
if (b.num == 0)
{
throw new DivideByZeroException();
}
return new Fraction(a.num * b.den, a.den * b.num);
}
public override string ToString() => $"{num} / {den}";
}
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
}
}
Вы можете расширить предыдущий пример, определив неявное преобразование из int
в Fraction
. Затем перегруженные операторы будут поддерживать аргументы этих двух типов. То есть можно будет добавить целое число к дроби и получить дробь.
Можно также использовать ключевое слово operator
для определения пользовательского преобразования типа. Дополнительные сведения см. в разделе Операторы пользовательского преобразования.
Перегружаемые операторы
В следующей таблице показаны операторы, которые могут быть перегружены:
Операторы | Примечания |
---|---|
+x , -x , !x , ~x , ++ , -- , true , false |
Операторы true и false должны быть перегружены вместе. |
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 |
Должен быть перегружен парами следующим образом: == и != , < и > , <= и >= . |
Неперегружаемые операторы
В следующей таблице показаны операторы, которые нельзя перегрузить.
Операторы | Альтернативные варианты |
---|---|
x && y , x || y |
Перегрузка операторов true и и false операторов & или | . Дополнительные сведения см. в разделе Пользовательские условные логические операторы. |
a[i] , a?[i] |
Определите индексатор. |
(T)x |
Определите преобразования пользовательских типов, которые могут выполняться выражением приведения. Дополнительные сведения см. в разделе Операторы пользовательского преобразования. |
+= , -= , *= , /= , %= , &= , |= , ^= , <<= , >>= , >>>= |
Перегрузка соответствующего двоичного оператора. Например, при перегрузке двоичного + оператора += неявно перегружается. |
^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 |
Нет. |
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#: