Поведение обработчика событий .net 1.1 против 2.0 с нулевым делегатом - PullRequest
1 голос
/ 08 октября 2008

Не уверен, что именно здесь происходит, но похоже, что в .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());
    }
}

Ответы [ 3 ]

1 голос
/ 08 октября 2008

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

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

if (ChartJoinedRowAdded != null)
      ChartJoinedRowAdded(new object())
1 голос
/ 08 октября 2008

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

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

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

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

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

0 голосов
/ 08 октября 2008

Способ работы событий на самом деле не изменился с 1,1 до 2

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

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

Запустит TableEventHandler, а затем делегат - ноль только что пропущен.

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

this.MyEvent = null;

Если ничего не подписано, ваше мероприятие будет недействительным - см. Ответ сораз. Класс DataTable будет содержать аналогичную проверку и не будет запускать событие, если нет подписчиков.

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

//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(...) );
}
...