щоб зрозуміти відмінності, ви можете переглянути ці 2 приклади
Приклад з Делегатами (Дія в цьому випадку є делегатом, який не повертає значення)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
щоб скористатися делегатом, вам слід зробити щось подібне
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
цей код працює добре, але у вас можуть бути слабкі місця.
Наприклад, якщо я це пишу
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
з останнього рядка коду я переосмислив попередню поведінку лише з одним відсутнім +
(я використовував +
замість +=
)
Ще одне слабке місце полягає в тому, що кожен клас, який використовує ваш Animal
клас, може підняти його RaiseEvent
просто animal.RaiseEvent()
.
Щоб уникнути цих слабких місць, ви можете використовувати events
c #.
Ваш клас Animal зміниться таким чином
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
називати події
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Відмінності:
- Ви використовуєте не загальнодоступну власність, а загальнодоступне поле (із подіями, які компілятор захищає ваші поля від небажаного доступу)
- Події не можна призначити безпосередньо. У цьому випадку ви не можете зробити попередню помилку, яку я виявив, переважаючи поведінку.
- Ніхто за межами вашого класу не може підняти подію.
- Події можуть бути включені в декларацію інтерфейсу, тоді як поле не може
примітки
EventHandler оголошено таким делегатом:
public delegate void EventHandler (object sender, EventArgs e)
він приймає відправника (типу Object) та аргументи події. Відправник недійсний, якщо він походить із статичних методів.
Ви також можете використовувати EventHAndler
цей приклад замість цьогоEventHandler<ArgsSpecial>
тут зверніться до документації про EventHandler