イベントハンドラーの動作の違い.NET 1.1と2.0のnullデリゲート
-
05-07-2019 - |
質問
ここで何が起こっているのか正確にはわかりませんが、.NET 1.1では初期化されていないイベントデリゲートは問題なく実行できますが、.NET 2.0+ではNullReferenceExceptionが発生します。理由は何でも。以下のコードは1.1では問題なく実行できますが、2.0ではNullReferenceExceptionが発生します。なぜそれが違う振る舞いをするのか興味がありますか?何が変わったのですか?
ありがとう
eg
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());
}
}
解決
[更新]知る限り、ここでは基本的なデリゲートの処理に変更はありません。違いは、DataTableの動作にあります。
しかし!特に静的メソッドではなく、インスタンスからサブスクライブする場合は、静的イベントの使用に注意してください。これは、オブジェクトの巨大なスワスを生かし、ガベージコレクションされないようにするための良い方法です。
1.1からcscを介してコードを実行すると、一般的なデリゲート側が同じであることがわかります。違いは、RowChangedを発生させるDataTableコードが例外を飲み込んでいたことです。たとえば、次のようなコードを作成します。
Console.WriteLine("Before");
ChartJoinedRowAdded(new object());
Console.WriteLine("After");
" Before"は表示されますが、" After"は表示されません。 DataTableによって例外がスローされ、飲み込まれました。
他のヒント
eventhandlerシステムは基本的に、特定のイベントが発生したときに呼び出す関数のリストにすぎません。
" null"に初期化されます。リストであり、空のリストではないので、行う必要があります
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はスキップされます。
nullを使用してイベントをクリアできますが、イベント発生クラス内のみです:
this.MyEvent = null;
サブスクライブするものがない場合、イベントは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(...) );
}