簡體   English   中英

為什么C#中的事件實現默認情況下不使用弱事件模式?

[英]Why is the implementation of events in C# not using a weak event pattern by default?

這個問題可能導致猜測性答案,但我認為在實現event背后有一個深思熟慮的設計決策。

只要事件的發布者處於活動狀態, 的事件模式就會使訂閱者保持活動狀態。 因此,如果你沒有取消訂閱,你就會泄漏內存(好吧,並沒有真正泄漏 - 但內存仍然不必要地占用)。

如果我想阻止這種情況,我可以取消訂閱事件或實現MSDN中提出的弱事件模式。

由於事件模式導致了很多問題(初學者?),問題是:為什么決定發布者保留對訂閱者的強引用,而不是讓它們獨立或允許開發人員明確地擁有strongweak修飾符?

關於這個主題已經有了幾個問題 ,答案聽起來很合理,但沒有一個真正回答為什么會這樣。

一個原因當然是表現 GC句柄(為WeakReference等所有“異國情調”引用提供動力)會帶來性能成本。 弱事件比“強”事件慢,因為它們需要GC句柄。 存儲委托的實例字段(默認情況下)實現強事件。 這只是一個普通的托管引用,與任何其他引用一樣便宜。

事件應該是一種非常通用的機制。 它們不僅適用於您可能擁有幾十個事件處理程序的UI場景。 將很多復雜性和性能成本烘焙到這樣一個基本語言功能中並不是一個明智的想法。

還存在由弱引用引起的語義差異非確定性 如果您將() => LaunchMissiles()掛鈎到某個事件,您可能會發現有時會啟動導彈。 其他時候GC已經帶走了處理程序。 這可以通過引入另一個復雜程度的從屬句柄來解決。

請注意,您可以透明地向訂戶實施弱事件。 事件就像屬性一樣,它們僅僅是基於addremove訪問器方法的元數據和約定。 所以這是(僅僅)關於.NET語言選擇的默認值的問題。 這不是CLR的設計問題。

我個人覺得很少有事件的強烈參考性質是一個問題。 通常,事件連接在具有相同或非常相似的生命周期的對象之間。 例如,您可以在ASP.NET中的HTTP請求的上下文中掛接所有您想要的事件,因為在請求結束時, 所有內容都有資格進行收集。 任何泄漏的大小都是有限的,而且壽命很短。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM