Поделиться через


Операторы - и -= — вычитание (минус)

Встроенные числовые типы, такие как целые и типы чисел с плавающей запятой, а также типы делегатов поддерживают операторы - и -=.

Для получения информации об арифметическом - операторе, см. разделы унарных операторов плюс и минус и оператора вычитания - в статье об арифметических операторах.

Удаление делегата

Для операндов одного типа делегата оператор возвращает экземпляр -, вычисляемый следующим образом:

  • Если оба операнда не равны null, а список вызовов правого операнда является правильным смежным подсписком списка вызовов левого операнда, результатом операции будет новый список вызовов, полученный путем удаления записей правого операнда из списка вызовов левого операнда. Если список операнда справа совпадает с несколькими непрерывными подсписками в списке операнда слева, удаляется только правый крайний из совпадающих подсписков. Если удаление приводит к пустому списку, результатом будет null.

    Action a = () => Console.Write("a");
    Action b = () => Console.Write("b");
    
    var abbaab = a + b + b + a + a + b;
    abbaab();  // output: abbaab
    Console.WriteLine();
    
    var ab = a + b;
    var abba = abbaab - ab;
    abba();  // output: abba
    Console.WriteLine();
    
    var nihil = abbaab - abbaab;
    Console.WriteLine(nihil is null);  // output: True
    
  • Если список вызовов правого операнда не является непрерывным подсписком списка вызовов левого операнда, результатом операции является левый операнд. Например, удаление делегата, который не является частью делегата многоадресной рассылки, не приводит ни к каким изменениям и оставляет делегата многоадресной рассылки без изменений.

    Action a = () => Console.Write("a");
    Action b = () => Console.Write("b");
    
    var abbaab = a + b + b + a + a + b;
    var aba = a + b + a;
    
    var first = abbaab - aba;
    first();  // output: abbaab
    Console.WriteLine();
    Console.WriteLine(object.ReferenceEquals(abbaab, first));  // output: True
    
    Action a2 = () => Console.Write("a");
    var changed = aba - a;
    changed();  // output: ab
    Console.WriteLine();
    var unchanged = aba - a2;
    unchanged();  // output: aba
    Console.WriteLine();
    Console.WriteLine(object.ReferenceEquals(aba, unchanged));  // output: True
    

    В предыдущем примере также показано, что при удалении делегатов экземпляры делегатов сравниваются. Например, делегаты, созданные из оценки идентичных лямбда-выражений , не равны. Дополнительные сведения о равенстве делегатов см. в разделе операторов равенства делегатовспецификации языка C#.

  • Если левый операнд имеет nullзначение, результатом операции является null. Если правый операнд является null, результатом операции является левый операнд.

    Action a = () => Console.Write("a");
    
    var nothing = null - a;
    Console.WriteLine(nothing is null);  // output: True
    
    var first = a - null;
    a();  // output: a
    Console.WriteLine();
    Console.WriteLine(object.ReferenceEquals(first, a));  // output: True
    

Чтобы объединить делегаты, используйте + оператор.

Дополнительные сведения о типах делегатов см. в разделе Делегаты.

Оператор назначения вычитания -=

Выражение с помощью оператора -=, например

x -= y

Эквивалентен

x = x - y

За исключением того, что x оценивается только один раз.

В следующем примере показано использование оператора -=:

int i = 5;
i -= 9;
Console.WriteLine(i);
// Output: -4

Action a = () => Console.Write("a");
Action b = () => Console.Write("b");
var printer = a + b + a;
printer();  // output: aba

Console.WriteLine();
printer -= a;
printer();  // output: ab

Оператор -= также используется для указания метода обработчика события, который нужно удалить при отмене подписки на событие. Дополнительные сведения см. в разделе Как подписаться и отменить подписку на события.

Перегрузка оператора

Определяемый пользователем тип может перегрузить оператор -. При перегрузке двоичного оператора - оператор -= также неявно перегружен. Начиная с C# 14 определяемый пользователем тип может явно перегружать -= оператор, чтобы обеспечить более эффективную реализацию. Как правило, тип перегружает оператор -=, так как значение можно обновить на месте, а не выделить новый экземпляр для хранения результата вычитания. Если тип не предоставляет явной перегрузки, компилятор создает неявную перегрузку.

Спецификация языка C#

Дополнительные сведения см. в разделах «Унарный минус» и «Оператора вычитания»спецификации языка C#. Дополнительные сведения о перегрузке операторов составных назначений в C# 14 и более поздних версиях см. в спецификации определяемой пользователем функции составного назначения .

См. также