В чем отличие использования события и просто делегата (по тому же назначению)? Т.е. что мы при обретем и что потеряем, убрав слово event в объявлении события?
Правильно, ли я понимаю, что определив события, мы просто не можем нарушить целостность списка получателей, и вообще вносить в него изменения только операторами += и -=? Ну и, кроме того, всяческие выгоды от собственноручного определения методов add_... и remove_... ?
/**********Comments***************************/
We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
Здравствуйте, Аноним, Вы писали:
А>Правильно, ли я понимаю, что определив события, мы просто не можем нарушить целостность списка получателей, и вообще вносить в него изменения только операторами += и -=? Ну и, кроме того, всяческие выгоды от собственноручного определения методов add_... и remove_... ?
Кроме того, мы еще не можем извне класса узнать, кто еще подписан на событие, а также мы не можем извне класса вызвать это событие. Это лучше удовлетворяет требованиям ООП и защищает нас от потенциально опасных архитектурных решений. Рассмотрите следующий код:
using System;
public delegate void MyDelegate();
public class EventDeclarator
{
public static MyDelegate PlainDelegate;
public static event MyDelegate Event;
public void FireEvent()
{
if (Event != null)
Event(); // так работаетif (PlainDelegate != null)
PlainDelegate(); // так тоже работает
}
}
public class Client
{
public static void WhatCanIDoWithPlainDelegate()
{
EventDeclarator.PlainDelegate += new MyDelegate(Foo);
// подписали метод Foo
EventDeclarator.PlainDelegate = new MyDelegate(Bar);
// подписали метод Bar, но при этом удалили других подписчиков, а они-то и не знают :)
Delegate[] subscribers = EventDeclarator.PlainDelegate.GetInvocationList();
// получили список всех подписчиков и теперь можем (через делегаты) дергать даже приватные методы классов
EventDeclarator.PlainDelegate();
// вызвали "событие" извне определяющего класса
}
public static void WhatCanIDoWithEvent()
{
EventDeclarator.Event += new MyDelegate(Foo);
// подписали метод Foo
EventDeclarator.Event = new MyDelegate(Bar); // не компилируется
Delegate[] subscribers = EventDeclarator.Event.GetInvocationList(); // не компилируется
EventDeclarator.Event(); // не компилируется
}
private static void Foo() { }
private static void Bar() { }
}
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Аноним, Вы писали:
А>>Правильно, ли я понимаю, что определив события, мы просто не можем нарушить целостность списка получателей, и вообще вносить в него изменения только операторами += и -=? Ну и, кроме того, всяческие выгоды от собственноручного определения методов add_... и remove_... ?
N>Кроме того, мы еще не можем извне класса узнать, кто еще подписан на событие, а также мы не можем извне класса вызвать это событие. Это лучше удовлетворяет требованиям ООП и защищает нас от потенциально опасных архитектурных решений. Рассмотрите следующий код:
...
Рассмотрел, спасибо! Исчерпывающий ответ
Напишу-ка сюда же. Вопрос другой, но по той же теме.
Есть событие, на которое подписываются методы, которые могут выбросить исключение. Как сделать так, чтобы независимо от содержания методов все они получали извещение о том, что событие произошло? Фактически, речь идет об асинхронном вызове этих методов, а не последовательным списком. Но BeginInvoke не работает: The delegate must have only one target.
Здравствуйте, SageMath, Вы писали:
SM>Напишу-ка сюда же. Вопрос другой, но по той же теме.
SM>Есть событие, на которое подписываются методы, которые могут выбросить исключение. Как сделать так, чтобы независимо от содержания методов все они получали извещение о том, что событие произошло? Фактически, речь идет об асинхронном вызове этих методов, а не последовательным списком. Но BeginInvoke не работает: The delegate must have only one target.
SM>Как тут быть?
если я верно понял вопрос, можно сделать, например, так:
public event EventHandler MyEvent;
public void RaiseMyEvent(EventArgs e)
{
if (MyEvent != null)
{
foreach (EventHandler handler in MyEvent.GetInvocationList())
{
try
{
handler(this, e);
}
catch (Exception ex)
{
//.. do something with exception
}
}
}
}