C # делегаты и методы подписи - PullRequest
7 голосов
/ 31 января 2011

С MSDN :

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

Итак, как это возможно:

public delegate void AlarmEventHandler(object sender, EventArgs e);
public event AlarmEventHandler Alarm;

protected virtual void OnAlarm(EventArgs e)
        {
            AlarmEventHandler handler = Alarm;
            if (handler != null)
            {
                // Invokes the delegates.
                handler(this, e);
            }
        }

делегат AlarmEventHander и событие AlarmEventHandler имеют разные подписи, но handler можно присвоить Alarm.

Возможно, я немного неправильно понимаю делегатов, и я был бы очень признателен, если бы кто-то мог объяснить, где я иду не так.

Ответы [ 5 ]

7 голосов
/ 31 января 2011

Делегат похож на класс. Событие похоже на собственность. Когда вы объявляете event в классе, вы объявляете тип события, которым оно является. В этом случае AlarmEventHandler, который является внутренним классом класса верхнего уровня, частью которого он является.

В методе OnAlarm вы получаете экземпляр класса AlarmEventHandler, который был назначен событию, и вызываете его.

Чтобы прояснить ситуацию, ваш код выше похож на этот, используя обычные классы и ссылки:

public class InnerClass {
    public void MyMethod() { /* ... */ }
}

public InnerClass MyProperty { get; set; }

protected virtual void CallMyMethod() {
    InnerClass cls = MyProperty;
    if (cls != null)
        cls.MyMethod();
}
2 голосов
/ 31 января 2011

На самом деле подписи одинаковы. В .NET события реализуются с делегатами.

public event AlarmEventHandler Alarm;

Таким образом, приведенный выше код на самом деле компилируется компилятором как:

private AlarmEventHandler handler;

public event AlarmEventHandler Alarm
{
    add { handler += value; }
    remove { handler -= value; }
}

Таким образом, событие фактически использует тот же AlarmEventHandler делегат.

0 голосов
/ 31 января 2011

Событие просто делегат.Доступ к делегату itselft возможен только изнутри класса.Со стороны только добавить и удалить функциональность для события возможно, вы можете сделать только это:

myAlarm.Alarm+=new AlarmEventHandler(callPolice);
// or
myAlarm.Alarm-=new AlarmEventHandler(callPolice);

Но изнутри классаAlarm - просто делегат типа AlarmEventHandler, поэтому вы можете делать то, что показывает ваш код:

        AlarmEventHandler handler = Alarm;
        if (handler != null)
        {
            // Invokes the delegates.
            handler(this, e);
        }
0 голосов
/ 31 января 2011

Функция, которая принимает базовый класс в качестве (не ссылочного) параметра, может быть преобразована в делегат, который принимает производный класс в качестве параметра. Это связано с тем, что функция, принимающая base, может быть безопасно заменена везде, где используется функция, которая принимает производный класс.

void TakesObject(object o)
{
...
}

Action<string> myAction=TakesObject;

Вы можете вызвать myAction, только передав строку. И поскольку каждая строка является объектом, контракт для TakesObject выполняется.

В вашем случае это работает, потому что каждый AlarmEventArgs тоже EventArgs. Таким образом, требования контракта вашего обработчика событий менее строги, чем контрактные гарантии для типа делегата, используемого событием.

Это называется со-и противо-дисперсией. У вас есть ко-дисперсия в типах возвращаемых данных и противоположная дисперсия в параметрах.

Проверьте эту статью на MSDN:
Использование дисперсии в делегатах (C # и Visual Basic)

0 голосов
/ 31 января 2011
  1. Вы смешиваете делегатов и события.Хотя события зависят от делегатов, они являются концепциями различий полностью.Так что следует принимать отдельно.
  2. Делегат похож на определение типа.Место, где вы используете этот делегат, похоже на переменную или свойство.
  3. Событие заставляет этого делегата вести себя иначе, чем снаружи.Подпись все та же.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...