C# 什么时候应该使用弱引用?

C# 什么时候应该使用弱引用?,c#,java,weak-references,C#,Java,Weak References,我最近遇到了一段带有weakreference的Java代码——我从未见过它们的部署,尽管我在引入它们时遇到过它们。这是应该常规使用的还是只有在遇到内存问题时才使用?如果是后者,它们可以很容易地被修改吗?或者代码是否需要认真地重构?普通的Java(或C#)程序员通常会忽略它们吗 编辑过度使用WRs会造成任何损害吗?只要你想引用某个对象,而不想让该对象保持活动状态,就可以使用WRs。这对于许多类似缓存的功能来说都是如此,但在事件处理中也扮演着重要角色,订阅服务器不能通过订阅事件而保持活动状态 一个

我最近遇到了一段带有weakreference的Java代码——我从未见过它们的部署,尽管我在引入它们时遇到过它们。这是应该常规使用的还是只有在遇到内存问题时才使用?如果是后者,它们可以很容易地被修改吗?或者代码是否需要认真地重构?普通的Java(或C#)程序员通常会忽略它们吗


编辑过度使用WRs会造成任何损害吗?

只要你想引用某个对象,而不想让该对象保持活动状态,就可以使用WRs。这对于许多类似缓存的功能来说都是如此,但在事件处理中也扮演着重要角色,订阅服务器不能通过订阅事件而保持活动状态


一个小例子:刷新某些数据的计时器事件。任何数量的对象都可以在计时器上订阅以获得通知,但它们在计时器上订阅的事实不应该让它们保持活动状态。因此计时器应该对对象有弱引用。

弱引用都是关于垃圾收集的。一个标准对象在所有引用被切断之前都不会“消失”,这意味着所有的引用都必须在垃圾收集会被认为是垃圾之前被移除。 由于对象被其他对象引用而使用弱引用并不一定意味着它不是垃圾。它仍然可以被GC提取并从内存中删除

举个例子:如果我的应用程序中有一堆Foo对象,我可能希望使用一个集合来保存我周围所有Foo的中心记录。但是,当我的应用程序的其他部分通过删除对某个Foo对象的所有引用来删除该对象时,我不希望我的集合保留的对该对象的其余引用阻止它被垃圾收集!真的,我只是想让它从我的布景中消失。在这里,您可以使用弱集(Java有一个WeakHashMap)之类的东西,它使用对其成员的弱引用,而不是“强”引用

如果您的对象没有在您希望的时候被垃圾收集,那么您在簿记中犯了一个错误,某些东西仍然保存着一个您忘记删除的引用。使用弱引用可以减轻这种簿记的痛苦,因为您不必担心它们会使对象保持“活动”和未垃圾收集,但您不必使用它们

任何损坏都可以通过以下方式造成: 过度使用WRs

是的,它可以

一个问题是弱引用会使代码更加复杂,并且可能容易出错。任何使用弱引用的代码都需要处理每次使用弱引用时引用被破坏的可能性。如果过度使用弱引用,最终会编写大量额外代码。(您可以通过将每个弱引用隐藏在负责检查的方法后面,并根据需要重新创建被丢弃的对象来缓解此问题。但这不一定像那样简单;例如,如果重新创建过程涉及网络访问,您需要处理重新创建失败的可能性。)

第二个问题是使用弱引用会带来运行时开销。显而易见的代价是创建弱引用并调用
get
。一个不太明显的代价是每次GC运行时都需要做大量额外的工作

最后一个问题是,如果对应用程序将来很可能需要的东西使用弱引用,则可能会导致重复创建它的成本。如果这一成本很高(在CPU时间、IO带宽、网络流量等方面),您的应用程序可能会因此表现不佳。您最好给JVM更多的内存,而不要使用弱引用


当然,这并不意味着您应该完全避免使用弱引用。只是你需要仔细想想。也许您应该首先在应用程序上运行内存分析器,找出内存使用问题的根源。

在考虑使用弱引用时,一个好问题是,如果弱引用在对象不存在强引用的瞬间失效,人们会有什么感觉。如果这会使WeakReference不那么有用,那么WeakReference可能不是最好的使用方法。如果这是对垃圾收集产生的非确定性失效的改进,那么WeakReference可能是正确的选择。

就我所知,弱引用的更多用法示例WR的唯一危险是您可能实际上需要强引用。如果您的对象在您不希望它们消失的时候开始消失,那么您可能已经走得太远了;)您必须知道何时使用它们以及如何使用它们,在某些情况下,这归结为与锁定数据的多线程处理类似的问题。例如,如果(x.IsAlive){x.Target.ToString();}对象可能同时已被收集,则将其发送到(.NET示例):
是错误的。您首先必须获取一个强引用,然后检查它是否仍然处于活动状态:
object t=x.Target;如果(t!=null){t.ToString();}
,因为一旦您重新获取了对对象的强引用,它将不会被收集。使用弱引用(尤其是通过
WeakHashMap
)可能会出错。例如,VM可能会注意到,它几乎可以在创建引用之后立即清除它们。这种情况确实会发生,尽管通常是在应用程序运行一段时间之后。tackline-我不确定是否“严重错误”-当然,如果它们在不应该使用的时候使用,那么应用程序将失败-但这是一个设计问题,我并不是说你应该只通过弱引用引用一个对象,而是说你可以用它们来保持对对象的引用