不确定这里究竟发生了什么,但似乎在.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());
}
}
答案 0 :(得分:1)
[更新] AFAIK,基本代表处理没有变化;不同之处在于DataTable的行为方式。
然而!使用静态事件要非常小心,特别是如果您从实例订阅(而不是静态方法)。这是保持大量物体存活并且不被垃圾收集的好方法。
通过csc从1.1运行代码显示一般委托方是相同的 - 我认为区别在于引发RowChanged的DataTable代码吞噬了异常。例如,制作如下代码:
Console.WriteLine("Before");
ChartJoinedRowAdded(new object());
Console.WriteLine("After");
你会看到“之前”,但没有“之后”; DataTable抛出并吞下了一个异常。
答案 1 :(得分:1)
事件处理程序系统基本上只是在引发给定事件时要调用的函数列表。
它初始化为“null”列表,而不是空列表,因此您需要执行
if (ChartJoinedRowAdded != null)
ChartJoinedRowAdded(new object())
答案 2 :(得分:0)
事件的工作方式并没有真正从1.1变为2
虽然语法看起来像普通聚合,但实际上并非如此:
dt.RowChanged += TableEventHandler;
dt.RowChanged += null;
dt.RowChanged += delegate (object sender, DataRowChangeEventArgs e) {
//anon
};
将触发TableEventHandler
然后触发委托 - 刚刚跳过null。
您可以使用null清除事件,但只能在事件触发类中使用:
this.MyEvent = null;
如果没有订阅您的活动将为空 - 请参阅soraz的回答。 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(...) );
}