2011-01-31 3 views
7

От MSDN:C# Делегаты и метод подписи

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

Так как это возможно:

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.

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

+0

Я думаю, вы путаете некоторые из ваших имен символов. В приведенном выше коде делегат называется «AlarmEventHandler», и событие, которое имеет тот же тип, называется «Тревога». Поскольку они имеют один и тот же тип, нет никаких проблем с назначением. Я думаю, что вас смущает метод «OnAlarm», который появляется, возможно, для ответа на другое событие с другим типом делегата. –

+0

См .: Поля, подобные событиям. http://msdn.microsoft.com/en-us/library/aa664455(v=vs.71).aspx – Ani

+0

Я не вижу проблемы здесь. Типы точно соответствуют (оба - «AlarmEventHandler»), поэтому можно было бы ожидать, что они смогут присвоить друг другу. – finnw

ответ

7

Делегат - это класс. Событие похоже на свойство. Когда вы объявляете 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(); 
} 
+0

Мне нравится, как вы это объяснили. это заставило меня представить, как это работает лучше – Notter

2

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

public event AlarmEventHandler Alarm; 

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

private AlarmEventHandler handler; 

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

Так событие действительно использует тот же самый AlarmEventHandler делегат.

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

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

void TakesObject(object o) 
{ 
... 
} 

Action<string> myAction=TakesObject; 

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

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

Это называется co- и contra-дисперсией. У вас есть совместная дисперсия в возвращаемых типах и противоречие в параметрах.

Проверить эту статью на MSDN:
Using Variance in Delegates (C# and Visual Basic)

0

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

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

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

 AlarmEventHandler handler = Alarm; 
     if (handler != null) 
     { 
      // Invokes the delegates. 
      handler(this, e); 
     } 
Смежные вопросы