Давайте разберем простой пример:
using System;
class Program
{
delegate bool MyFilter(int x);
bool IsOdd(int x)
{
return x % 2 == 1;
}
static void Main()
{
MyFilter f = new Program().IsOdd;
Console.WriteLine(f(5));
}
}
Что делает компилятор?Давайте начнем с этой строки:
delegate bool MyFilter(int x);
Компилятор генерирует тип , который выглядит примерно так:
class MyFilter : MulticastDelegate
{
public MyFilter(Object thisRef, IntPtr method);
public bool Invoke(int x);
// BeginInvoke(), EndInvoke() - Let's ignore those
}
Тип MyFilter имеет конструктор, который принимает двапараметры: IntPtr для тела метода, чтобы вызвать, и Объект, для которого этот метод должен быть вызван.Метод Invoke () для типа MyFilter вызывает фактический делегат.
Теперь давайте посмотрим, что происходит в методе Main ().Компилятор перепишет его примерно так:
static void Main()
{
MyFilter f = new MyFilter(new Program(), addressof(Program.IsOdd));
Console.WriteLine(f.Invoke(5));
}
Конечно, addressof не является действительным оператором C #, но вы можете себе представить, что он возвращает адрес тела для переданного метода.Кроме того, я не обсуждал различные другие темы, связанные с делегатами, такие как цепочка (это функция, предоставляемая базовым классом MulticastDelegate), но, надеюсь, я рассмотрел ваш вопрос.
Подводя итог, опорные точки делегатак объекту, который реализует метод Invoke, который соответствует подписи делегата.Объект отслеживает указатель на метод, который необходимо вызвать, а также целевой объект, для которого вызывается метод (если метод не является статическим).