web-dev-qa-db-ja.com

nullを割り当てると、オブジェクトからすべてのイベントハンドラーが削除されますか?

クラスに新しいメンバーを定義しました

protected COMObject.Call call_ = null;

このクラスには、私がサブスクライブした次のイベントハンドラがあります。

call_.Destructed += new COMObject.DestructedEventHandler(CallDestructedEvent);

イベントハンドラーを削除すると、メンバーがnullに設定されますか?

call_ = null;

または-=で購読を解除する必要がありますか?

32
Dor Cohen

はい、オーバーロードされた-=を使用して、イベントの登録を解除する必要があります。

nullへの参照を割り当てるだけでは、自動的には行われません。オブジェクトは引き続きそのイベントを待機します。

30
Azodious

以下のMSDNの抜粋にあるように、nullに設定するか、オブジェクトを破棄する前に、常に-=でイベントハンドラーをサブスクライブ解除する必要があります(単に変数をnullに設定しても、すべてのハンドラーのサブスクライブは解除されません)。

イベントが発生したときにイベントハンドラーが呼び出されないようにするには、単にイベントをサブスクライブ解除します。リソースリークを防ぐために、サブスクライバーオブジェクトを破棄する前に、イベントのサブスクライブを解除することが重要です。イベントのサブスクライブを解除するまで、パブリッシングオブジェクトのイベントの基になるマルチキャストデリゲートは、サブスクライバーのイベントハンドラーをカプセル化するデリゲートへの参照を持っています。パブリッシングオブジェクトがその参照を保持している限り、サブスクライバーオブジェクトはガベージコレクションされません。

Unsubscribingセクションの以下のリンクで説明されています:

方法:イベントのサブスクライブとサブスクライブ解除(C#プログラミングガイド)

詳細については:

イベントハンドラーを常にunscubscribeする必要がある理由

8
VS1

イベントから nsubscribe に減算代入演算子(-=)を使用する必要があります。すべてのサブスクライバーがイベントのサブスクライブを解除した後でのみ、パブリッシャークラスのイベントインスタンスはnullに設定されます。

すべてのイベントを削除し、イベントが「アクション」タイプであると想定します。

Delegate[] dary = TermCheckScore.GetInvocationList();

if ( dary != null )
{
    foreach ( Delegate del in dary )
    {
        TermCheckScore -= ( Action ) del;
    }
}
1
Googol