Ответ 1
+=
подписывается на событие. Делегат или метод в правой части +=
будет добавлен во внутренний список, который отслеживает событие, и когда класс владельца запускает это событие, все делегаты в списке будут вызваны.
public void Bar()
{
Foo foo = new Foo();
**foo.MyEvent += foo_MyEvent;**
foo.FireEvent();
}
void foo_MyEvent(object sender, EventArgs e)
{
((Foo)sender).MyEvent -= foo_MyEvent;
}
Эй, я немного не знаком с событиями, может кто-нибудь сказать мне, что делает оператор + = с событиями?
+=
подписывается на событие. Делегат или метод в правой части +=
будет добавлен во внутренний список, который отслеживает событие, и когда класс владельца запускает это событие, все делегаты в списке будут вызваны.
Ответ, который вы приняли, - это упрощенная версия того, что делает +=
, но это не полная история.
Оператор +=
вызывает метод добавления в событии. Аналогично -=
вызывает удаление. Обычно это приводит к добавлению делегата во внутренний список обработчиков, вызываемых при запуске события, но не всегда.
Совершенно можно определить add, чтобы сделать что-то еще. Этот пример может помочь продемонстрировать, что происходит, когда вы вызываете +=
:
class Test
{
public event EventHandler MyEvent
{
add
{
Console.WriteLine("add operation");
}
remove
{
Console.WriteLine("remove operation");
}
}
static void Main()
{
Test t = new Test();
t.MyEvent += new EventHandler (t.DoNothing);
t.MyEvent -= null;
}
void DoNothing (object sender, EventArgs e)
{
}
}
Вывод:
add operation remove operation
Более подробную информацию см. в статье Jon Skeet, посвященной событиям и делегатам.
В этом случае метод foo_MyEvent загорается, когда вызывается это событие (поэтому вы подписываетесь на событие в строке 4)
Событие - это просто неизменный список делегатов (т.е. подписчики, которые будут вызваны, когда что-то публикует/вызывает это событие). Вы могли бы утверждать, что мы могли бы использовать List вместо этого. Если бы мы пошли таким образом, кто-то мог бы закалить наших подписчиков.
В приведенном выше сценарии, где вы используете List, вы можете сделать:
lstDelegate = newDelegate
и вы уничтожили существующих подписчиков (lstDelegate только содержит обратный вызов делегата ur сейчас).
Чтобы остановить это поведение, у нас есть Event. Когда вы используете событие, complier не позволит вам это сделать, вам разрешено добавлять/удалять собственный делегат, используя + = и - =. Это то, что я пытаюсь все равно различить. надеюсь, что это поможет.
Он добавляет обработчик к событию. Это означает, что метод с правой стороны оператора будет вызываться, когда событие будет поднято.
Одной из замечательных особенностей делегатов является то, что вы можете объединить их вместе. Это называется многоадресной рассылкой. Вы можете использовать оператор + или + =, чтобы добавить другой метод в список вызовов существующего экземпляра делегата. Аналогично, вы также можете удалить метод из списка вызовов, используя оператор присваивания декремента (- или - =). Эта функция служит основой для событий в С#. Ниже приведен пример многоадресного делегата.
class Program
{
static void Hello(string s)
{
Console.WriteLine(" Hello, {0}!", s);
}
static void Goodbye(string s)
{
Console.WriteLine(" Goodbye, {0}!", s);
}
delegate void Del(string s);
static void Main()
{
Del a, b, c, d;
// Create the delegate object a that references
// the method Hello:
a = Hello;
// Create the delegate object b that references
// the method Goodbye:
b = Goodbye;
// The two delegates, a and b, are composed to form c:
c = a + b;
// Remove a from the composed delegate, leaving d,
// which calls only the method Goodbye:
d = c - a;
Console.WriteLine("Invoking delegate a:");
a("A");
Console.WriteLine("Invoking delegate b:");
b("B");
Console.WriteLine("Invoking delegate c:");
c("C");
Console.WriteLine("Invoking delegate d:");
d("D");
/* Output:
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
*/
Console.ReadLine();
}
}
Все это возможно, поскольку делегаты наследуются от класса System.MulticastDelegate, который, в свою очередь, наследуется от System.Delegate. Из-за этого вы можете использовать члены, определенные в этих базовых классах для ваших делегатов. Вы можете узнать больше об этом в статье Делегаты и события в С#.NET