"Событие XXX может появляться только в левой части + = или - = blabla"
Это на самом деле потому, что C # - это"OO достаточно". Одним из основных принципов ООП является инкапсуляция; события предоставляют форму этого, как и свойства: внутри объявленного класса они могут быть доступны напрямую, но снаружи они доступны только для операторов +=
и -=
. Это сделано для того, чтобы декларирующий класс полностью контролировал время вызова событий. Код клиента может иметь только слово в , что происходит , когда они вызываются.
Причина, по которой ваш код RegisterLogger(p.OnStart)
компилируется, состоит в том, что он объявлен из области действия Program
класса, где объявлено событие Program.OnStart
.
Причина, по которой ваш код RegisterLogger(cs.OnStart)
не не компилируется , заключается в том, что он объявлен изнутри класса Program
, но событие MyCSharpProgram.OnStart
объявлено (очевидно) в MyCSharpProgram
класс.
Как указывает Крис Тейлор , причина, по которой вы получаете NullReferenceException
в строке p.OnStart(p, EventArgs.Empty);
, заключается в том, что при вызове RegisterLogger
при его наличии назначает новое значение локальной переменной не оказывает влияния на объект, которому была назначена эта локальная переменная, когда она была передана в качестве параметра . Чтобы лучше это понять, рассмотрим следующий код:
static void IncrementValue(int value)
{
value += 1;
}
int i = 0;
IncrementValue(i);
// Prints '0', because IncrementValue had no effect on i --
// a new value was assigned to the COPY of i that was passed in
Console.WriteLine(i);
Так же, как метод, который принимает int
в качестве параметра и присваивает ему новое значение, влияет только на локальную переменную, скопированную в его стек, метод, который принимает EventHandler
в качестве параметра и назначает новое значение it влияет только на ее локальную переменную (в присваивании).