Разница в поведении обработчика событий .net 1.1 и 2.0 с нулевым делегатом

StackOverflow https://stackoverflow.com/questions/181775

Вопрос

Не знаю, что именно здесь происходит, но похоже, что в .NET 1.1 неинициализированный делегат событий может работать без проблем, но в .NET 2.0+ это вызывает исключение NullReferenceException.Есть идеи, почему.Код ниже будет работать без проблем в версии 1.1, а в версии 2.0 выдает исключение NullReferenceException.Мне интересно, почему он ведет себя по-другому?Что изменилось?

Спасибо

например

class Class1
    {
    public delegate void ChartJoinedRowAddedHandler(object sender);



    public static event ChartJoinedRowAddedHandler ChartJoinedRowAdded;
    public static DataTable dt;

    public static void Main()
    {           
        dt = new DataTable();
        dt.RowChanged += new DataRowChangeEventHandler(TableEventHandler);

        object [] obj = new object[]{1,2};
        dt.Columns.Add("Name");
        dt.Columns.Add("Last");
        dt.NewRow();
        dt.Rows.Add(obj);
    }

    private static void TableEventHandler(object sender, DataRowChangeEventArgs e)
    {
        ChartJoinedRowAdded(new object());
    }
}
Это было полезно?

Решение

[обновлено] AFAIK, здесь не было никаких изменений в фундаментальной обработке делегатов;разница заключается в том, как ведет себя DataTable.

Однако!Будьте очень осторожны при использовании статических событий, особенно если вы подписываетесь на экземпляры (а не на статические методы).Это хороший способ сохранить в живых огромные массивы объектов и не подвергать их сборке мусора.

Запуск кода через csc из версии 1.1 показывает, что общая сторона делегата та же самая - я думаю, разница в том, что код DataTable, который вызывает RowChanged, поглощает исключение.Например, создайте код, как показано ниже:

    Console.WriteLine("Before");
    ChartJoinedRowAdded(new object());
    Console.WriteLine("After");

Вы увидите «До», но не «После»;исключение было выброшено и проглочено DataTable.

Другие советы

Система обработчиков событий — это, по сути, просто список функций, которые нужно вызывать при возникновении определенного события.

Он инициализируется «нулевым» списком, а не пустым списком, поэтому вам нужно сделать

if (ChartJoinedRowAdded != null)
      ChartJoinedRowAdded(new object())

Принцип работы событий практически не изменился с версии 1.1 на версию 2.

Хотя синтаксис выглядит как обычное агрегирование, на самом деле это не так:

dt.RowChanged += TableEventHandler;
dt.RowChanged += null;
dt.RowChanged += delegate (object sender, DataRowChangeEventArgs e) {
    //anon
};

Будет стрелять TableEventHandler а затем делегат - ноль просто пропускается.

Вы можете использовать значение null для очистки событий, но только внутри класса запуска событий:

this.MyEvent = null;

Если ничего не подпишется, ваше событие будет нулевым — см. ответ Сораза.А DataTable class будет содержать аналогичную проверку и не будет запускать событие, если нет подписчиков.

Стандартный шаблон:

//events should just about always use this pattern: object, args
public static event EventHandler<MyEventArgs> ChartJoinedRowAdded;


//inheriting classes can override this event behaviour
protected virtual OnChartJoinedRowAdded() {
    if( ChartJoinedRowAdded != null )
        ChartJoinedRowAdded( this, new MyEventArgs(...) );
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top