3

コード内のメモリ リークをクリーンアップし、それ以上のリークを防止するためのチェックを行うよう依頼されました。切り離されていないハンドラーが主な原因であるように思われることに気付きました。ほとんどは単純明快ですが、コードには頭を悩ませたことがいくつかあります。

初め:

myObject.someEvent -= null;

それがまったく何もしないと仮定するのは正しいですか?(イベントがローカルの場合、本質的にマルチキャスト デリゲートであるため、イベントを null に設定できることはわかっています)。

次に、匿名ハンドラーの場合:

myObject.someEvent += ()=> { x + y; };
myObject.someEvent -= ()=> { x + y; };

匿名メソッドは 2 つの別個のデリゲートとしてコンパイルされるため、2 番目の命令も同様に価値がないと言っているのは正しいのでしょうか? (これを解決するための適切な解決策を探している人は、こちらを参照してください)。

「ええ、そうです」で解決したくありません。なぜこれらのことがうまくいかないのか知りたいです(私の主張が正しいと仮定して)。

4

4 に答える 4

3

ドキュメントから:

匿名関数を使用してイベントをサブスクライブした場合、イベントのサブスクライブを簡単に解除できないことに注意することが重要です。このシナリオでサブスクライブを解除するには、イベントをサブスクライブするコードに戻り、anonymousメソッドをデリゲート変数に格納してから、デリゲートをイベントに追加する必要があります。一般に、コードの後半でイベントのサブスクライブを解除する必要がある場合は、匿名関数を使用してイベントをサブスクライブしないことをお勧めします。

ですから、あなたは正しいです、あなたはそのような匿名の方法を取り除くことはできません。同様に、言う myObject.someEvent -= null;ことも何もしません

于 2012-07-23T15:26:48.993 に答える
2

MulticastDelegate.CombineImpl最初のケースでは、 (IL Spyなどを使用して)逆コンパイルされた実装から、渡されたデリゲートがnull結合されていない場合、結合は行われないことがわかります。つまり、nullデリゲートを削除しても何も起こりません。


2番目のケースでは、コンパイラが2つのラムダ式を等しいと見なすかどうかによって異なります。この正確な質問は、このブログ記事で間接的に回答されています

次の場合はC#で:

Func<int, int> f1 = (int x)=>x + 1;
Func<int, int> f2 = (int x)=>x + 1;
bool b = object.ReferenceEquals(f1, f2);

<< snip >> C#では、これは実装定義のままです; コンパイラーは、その裁量でそれらを等しく参照するかどうかを選択できます。

現在のC#コンパイラがこれら2つが等しいかどうかを簡単に判断できるかどうかはわかりますが、それは実際には重要ではありません。これは実装で定義された動作であり、信頼すべきではありません。

于 2012-07-23T15:27:36.997 に答える
0

追加しても問題ないようです:

public Action  del;
void Main()
{

del+=(()=>"1".Dump());

 del+=null;
 del+=null;
 del+=null; 

del+=(()=>"2".Dump());
del();
del.GetInvocationList().Select(f=>f.Target);

}



//ouput:
1
2
于 2012-07-23T15:24:39.257 に答える
0

匿名メソッドは 2 つの別個のデリゲートとしてコンパイルされるため、2 番目の命令も価値がありません。したがって、減算は、削除する必要がある正しいハンドラーを実際には指していません。

正しい。各ラムダは新しいデリゲート オブジェクトを作成しますが、これは最初のものとは異なります。

そして、それがノーオペレーションでない場合、最初にスローすることを期待します(それがどのように役立つかわかりません。)

于 2012-07-23T15:24:43.687 に答える