Richard Deeming
Это стандартная подпись делегата для обработчиков событий.
Рекомендации .NET Framework указывают, что тип делегата, используемый для события, должен принимать два параметра: параметр "источник объекта", указывающий источник события, и параметр "e", инкапсулирующий любую дополнительную информацию о событии. Тип параметра "e" должен быть производным от EventArgs
класс. Для событий, которые не используют никакой дополнительной информации, платформа .NET Framework уже определила соответствующий тип делегата: EventHandler
.
То
sender
параметр-это экземпляр объекта, вызвавшего событие. Код класса, вызывающего событие, отвечает за передачу правильного объекта обработчику. В случае
static
события, этот параметр будет
null
.
То
e
параметр является либо экземпляром
EventArgs
класс, если событие не имеет дополнительных данных для передачи; или экземпляр класса, производного от
EventArgs
, который будет содержать данные, связанные с событием. Опять же, класс, который вызывает событие, отвечает за создание и заполнение этого аргумента.
Эта подпись-всего лишь рекомендация. Ничто не мешает классу определить событие с совершенно другой сигнатурой. Тем не менее, большинство классов соблюдают принципы фреймворка, и настоятельно рекомендуется, чтобы ваши собственные классы делали то же самое.
Основное преимущество этого синтаксиса заключается в том, что обработчики не должны меняться, если класс отправителя решает добавить новые данные в событие. Если бы данные просто передавались в качестве аргументов обработчику, это не сработало бы.
Например:
// v1:
public class Source
{
public delegate void FooEvent();
public event FooEvent Foo;
public void Bar()
{
FooEvent handler = Foo;
if (handler != null) handler();
}
}
public class Subscriber
{
public Subscriber(Source source)
{
source.Foo += Source_OnFoo;
}
private void Source_OnFoo()
{
...
}
}
// v2:
public class Source
{
public delegate void FooEvent(int answer);
public event FooEvent Foo;
public void Bar()
{
FooEvent handler = Foo;
if (handler != null) handler(42);
}
}
public class Subscriber
{
public Subscriber(Source source)
{
// Compiler error.
// The handler method needs to be updated to match the new signature.
source.Foo += Source_OnFoo;
}
private void Source_OnFoo()
{
...
}
}
Когда вы следуете рекомендациям, это не проблема:
// v1:
public class Source
{
public event EventHandler Foo;
public void Bar()
{
EventHandler handler = Foo;
if (handler != null) handler(this, EventArgs.Empty);
}
}
public class Subscriber
{
public Subscriber(Source source)
{
source.Foo += Source_OnFoo;
}
private void Source_OnFoo(object sender, EventArgs e)
{
...
}
}
// v2:
public class FooEventArgs : EventArgs
{
public FooEventArgs(int answer)
{
Answer = answer;
}
public int Answer { get; private set; }
}
public class Source
{
public event EventHandler<FooEventArgs> Foo;
public void Bar()
{
EventHandler<FooEventArgs> handler = Foo;
if (handler != null) handler(this, new FooEventArgs(42));
}
}
public class Subscriber
{
public Subscriber(Source source)
{
// This still works, because delegates are covariant:
source.Foo += Source_OnFoo;
}
private void Source_OnFoo(object sender, EventArgs e)
{
...
}
}