+ = оператор для делегата
Я знаю, что оператор + = добавит метод в список вызовов, поддерживаемый базовым объектом Delegate, например
using System;
class Program
{
delegate void MyDelegate(int n);
void Foo(int n)
{
Console.WriteLine("n = {0}", n)
}
static void Main(string[] args)
{
MyDelegate d = new MyDelegate(Foo);
d += Foo; // add Foo again
d.Invoke(3); // Foo is invoked twice as Foo appears two times in invocation list
}
}
Но когда я смотрю MSDN Delegate, MulticastDelegate, я не могу найти определение оператора + =. Как это работает? Автоматическая генерация компилятора?
Ответы
Ответ 1
Это не оператор самого типа делегата, в терминах IL - он определен в спецификации языка, но вы не найдете его, используя отражение. Компилятор превращает его в вызов Delegate.Combine
. В обратном режиме с использованием -
или -=
используется Delegate.Remove
.
По крайней мере, как это реализовано, когда С# нацеливает .NET, как это почти всегда. Теоретически это спецификация среды - спецификация языка не требует, чтобы компилятор использовал Delegate.Combine
или Delegate.Remove
, а в другой среде могут отсутствовать эти методы.
Из спецификации С# 5, раздел 7.8.4 (дополнение):
Двоичный оператор +
выполняет объединение делегатов, когда оба операнда имеют тип делегата D
. (Если операнды имеют разные типы делегатов, возникает ошибка времени привязки.) Если первый операнд null
, результатом операции является значение второго операнда (даже если это также null
). В противном случае, если второй операнд null
, то результатом операции является значение первого операнда. В противном случае результатом операции будет новый экземпляр делегата, который при вызове вызывает первый операнд, а затем вызывает второй операнд. Примеры объединения делегатов см. В §7.8.5 и § 15.4. Поскольку System.Delegate
не является типом делегата, оператор +
для него не определен.
Ответ 2
То же, что и с Int32
, String
и т.д. Оператор +
определяется неявно языком.
Вы можете проверить исходный код Delegate
, MulticastDelegate
, Int32
и т.д. Там нет перегрузок operator +
, поэтому он не появляется в MSDN документация.
Из спецификации языка С#, раздел 7.8.4:
Ниже перечислены предопределенные операторы сложения.
(...)
• Комбинация делегатов. Каждый тип делегата неявно предоставляет следующий предопределенный оператор, где D - тип делегата:
D operator +(D x, D y);
Существует разница между простыми типами и делегатами. Спецификация языка С# не требует, чтобы делегат был реализован с помощью System.Delegate
4.2.7 Типы делегатов
Делегат - это структура данных, которая ссылается на один или несколько методов. Например, методы также относятся к соответствующим экземплярам объектов. Ближайшим эквивалентом делегата в C или С++ является указатель на функцию, но в то время как указатель на функцию может ссылаться только на статические функции, делегат может ссылаться как на статические, так и на методы экземпляра. В последнем случае делегат хранит не только ссылку на точку входа методов, но также ссылку на экземпляр объекта, для которого нужно вызвать метод. Типы делегатов описаны в §15.
Обратите внимание, что здесь нет упоминания System.Delegate
. Сравните его с разделом 4.1.4 Простые типы:
С# предоставляет набор предопределенных типов структур, называемых простыми типами. Простые типы идентифицируются с помощью зарезервированных слов, но эти зарезервированные слова являются просто псевдонимами для предопределенных типов структуры в пространстве имен System, как описано в таблице ниже.
Зарезервированное слово Алиасный тип
sbyte System.SByte
byte System.Byte
короткая System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
двойной System.Double
bool System.Boolean
decimal System.Decimal
Или Раздел 4.2.4 Тип строки
(...)
Строка ключевого слова - это просто псевдоним для предопределенного класса System.String.
Таким образом, разрешение оператора + для делегатов на Delegate.Combine
представляет собой деталь реализации компиляторов С# в .NET framework.