看看下面的C#類:如何清除C#中的事件訂閱?
c1 {
event EventHandler someEvent;
}
如果有大量的訂閱到c1
的someEvent
事件,我想清楚了他們,什麼是實現這一目標的最佳途徑? 另請考慮對此事件的訂閱可能是lambda /匿名代理。
目前我的解決方案是將ResetSubscriptions()
方法添加到c1
,將someEvent
設置爲空。我不知道這是否有任何看不見的後果。
看看下面的C#類:如何清除C#中的事件訂閱?
c1 {
event EventHandler someEvent;
}
如果有大量的訂閱到c1
的someEvent
事件,我想清楚了他們,什麼是實現這一目標的最佳途徑? 另請考慮對此事件的訂閱可能是lambda /匿名代理。
目前我的解決方案是將ResetSubscriptions()
方法添加到c1
,將someEvent
設置爲空。我不知道這是否有任何看不見的後果。
從類內部,您可以將(隱藏)變量設置爲null。空引用是有效地表示空調用列表的規範方式。
從課外,你不能這樣做 - 事件基本上暴露「訂閱」和「取消訂閱」,就是這樣。
值得注意的是場外事件實際上在做什麼 - 他們在同一時間創建變量和事件。在課堂中,你最終引用變量。你從外面引用這個事件。
查看我的article on events and delegates瞭解更多信息。
使用Delegate.Remove或Delegate.RemoveAll方法添加一個方法C1,將設置「someEvent」爲空...
class c1
{
event EventHandler someEvent;
ResetSubscriptions() {someEvent = null;}
}
你可以做到這一點。
我不相信這將適用於lambda表達式或匿名代表。 – programmer 2008-09-30 15:45:13
這將是一個很好的建議,但你沒有例子... – 2013-11-27 23:25:45
在類作品中將事件設置爲null。當你處理一個類時,你應該總是將事件設置爲null,GC有事件的問題,並且如果事件懸而未決,可能無法清理處置的類。
概念性延長無聊的評論。
我寧願使用「事件處理程序」而不是「事件」或「委託」這個詞。其他的東西使用「事件」一詞。在一些編程語言(VB.NET,Object Pascal,Objective-C)中,「事件」被稱爲「消息」或「信號」,甚至有一個「消息」關鍵字和特定的糖語法。
const
WM_Paint = 998; // <-- "question" can be done by several talkers
WM_Clear = 546;
type
MyWindowClass = class(Window)
procedure NotEventHandlerMethod_1;
procedure NotEventHandlerMethod_17;
procedure DoPaintEventHandler; message WM_Paint; // <-- "answer" by this listener
procedure DoClearEventHandler; message WM_Clear;
end;
而且,爲了迴應稱「消息」,一個「事件處理程序」響應,無論是單委託或多個委託。
總結: 「事件」是「問題」,「事件處理程序」是答案。
清除所有訂閱者的最佳做法是,如果要將此功能公開給外部,請將someEvent設置爲null,方法是添加另一個公共方法。這沒有看不到的後果。前提是要記住用關鍵字'event'聲明SomeEvent。
請參見本書 - C#4.0中概括地說,第125頁
有人在這裏建議用Delegate.RemoveAll
方法。如果你使用它,示例代碼可以遵循下面的表格。但它真的很愚蠢。ClearSubscribers()
函數裏面爲什麼不是SomeEvent=null
?
public void ClearSubscribers()
{
SomeEvent = (EventHandler) Delegate.RemoveAll(SomeEvent, SomeEvent);// Then you will find SomeEvent is set to null.
}
Delegate[] dary = TermCheckScore.GetInvocationList();
if (dary != null)
{
foreach (Delegate del in dary)
{
TermCheckScore -= (Action) del;
}
}
class c1
{
event EventHandler someEvent;
ResetSubscriptions() {someEvent = delegate{};}
}
這是更好地使用委託{}不是空
這是我的解決方案:
public class Foo : IDisposable
{
private event EventHandler _statusChanged;
public event EventHandler StatusChanged
{
add
{
_statusChanged += value;
}
remove
{
_statusChanged -= value;
}
}
public void Dispose()
{
_statusChanged = null;
}
}
您需要撥打Dispose()
或使用using(new Foo()){/*...*/}
模式來取消訂閱調用列表的所有成員。
你確定分配null會清除調用列表嗎? – leppie 2008-09-30 15:37:16
這就是我所看到的行爲。正如我在我的問題中所說的,我不知道我是否忽略了某些事情。 – programmer 2008-09-30 15:42:54