アップデート
ここからのさまざまな回答を組み合わせて、新しい質問に対する「決定的な」回答を作成しました。
元の質問
私のコードには、アプリケーションの存続期間全体にわたって存在するイベント パブリッシャーがあります (ここでは必要最小限に縮小されています)。
public class Publisher
{
//ValueEventArgs<T> inherits from EventArgs
public event EventHandler<ValueEventArgs<bool>> EnabledChanged;
}
このパブリッシャーはあらゆる場所で使用できるため、すべてのサブスクライバーで処理コードを書き直さなくても済むように、この小さなヘルパー クラスを作成できたことに非常に満足しています。
public static class Linker
{
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged += (s, e) => subscriber.Enabled = e.Value;
}
//(Non-lambda version, if you're not comfortable with lambdas)
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged +=
delegate(object sender, ValueEventArgs<bool> e)
{
subscriber.Enabled = e.Value;
};
}
}
小さなマシンで使い始めるまでは問題なく動作していましたが、時折発生するようになりました。
System.ComponentModel.Win32Exception
Not enough storage is available to process this command
結局のところ、サブスクライバー コントロールが動的に作成、追加、およびフォームから削除されるコード内の場所が 1 つあります。ガベージ コレクションなどについての高度な理解 (つまり、昨日まで何もなかった) を考えると、ほとんどの場合、サブスクライバーもアプリケーションの存続期間中存続するため、後片付けをするとは思いもしませんでした。
私はしばらくの間、Dustin Campbell の WeakEventHandlerをいじりましたが、匿名のデリゲートでは機能しません(とにかく私にとってはそうではありません)。
とにかくこの問題はありますか?ショップ全体で定型コードをコピーして貼り付ける必要はありません。
(ああ、わざわざコントロールを作成したり破棄したりする理由を私に尋ねることは気にしないでください。それは私の設計上の決定ではありません...)
(PS: これは winforms アプリケーションですが、VS2008 と .Net 3.5 にアップグレードしました。Weak Event パターンの使用を検討する必要がありますか?)
(PPS:Rory からの良い答えですが、誰かが WeakEventHandler に相当するものを思いつくことができれば、明示的に UnLink/Dispose することを覚えておく必要がなくなります。それはクールです...)
編集問題のコントロールを「リサイクル」することで、この問題を回避したことを認めなければなりません。ただし、使用していた「キー」が明らかに一意ではないため、回避策が戻ってきて私を悩ませています(すすり泣く)。ここで他のリンクを発見しました(これを試してみました-少し弱すぎるようです-ターゲットがまだ生きていてもGCはデリゲートをクリアします。以下のs、oɔɯǝɹの回答と同じ問題です)、ここ(パブリッシャーを変更する必要があり、そうではありません匿名のデリゲートでは実際には機能しません) およびhere (Dustin Campbell による不完全として引用)。
私が探しているものは意味的に不可能かもしれないと思います.クロージャーは「私がいなくなった後でもぶらぶらする」ように設計されています.
私は別の回避策を見つけたので、神々からの声を待って、それを使い続けます.