.NET中是否存在弱引用?

4

我想在我的应用程序中保留某个类别的对象列表。但我仍希望该对象被垃圾回收。你能在.NET中创建弱引用吗?

参考:

来自MSDN的答案:

要使用对象建立弱引用,需要使用WeakReference创建一个实例,并将其设置为跟踪的对象实例。然后将Target属性设置为该对象,再将该对象设置为null。有关代码示例,请参见类库中的WeakReference。

4个回答

12

5

你能在.NET中创建弱引用吗?

可以:

WeakReference r = new WeakReference(obj);

使用System.WeakReference


3

是的...

这里有一个很好的例子:

http://web.archive.org/web/20080212232542/http://www.robherbst.com/blog/2006/08/21/c-weakreference-example/

在你的类中,你创建了两个成员变量:

WeakReference _weakRef = null;

Person _strongRef = null;

你创建了两个新的 Person 对象(这些对象是我为这个例子创造的简单对象,包含一个 Name 属性和一些引用跟踪代码)。接下来,你将成员变量设置为新创建的 Person 对象实例。
_strongRef = p;

_weakRef = new WeakReference(p1);

你会发现这里的区别在于,_strongRef只是一个普通的引用,而_weakRef是使用person对象(p1)作为构造函数中的参数设置为WeakReference对象。

如果进行垃圾回收,或者出于测试目的自己调用它:

GC.Collect();

然后由 _weakRef 成员变量持有的 p1 目标对象应该被垃圾回收。您可以编写代码进行检查:

if (_weakRef.IsAlive)

如果这个WeakReference仍然有效,你可以使用下面的代码将其转换为强引用或普通引用:
Person p = _weakRef.Target as Person;

现在,p 引用被视为强引用,并且只有在不再使用时才会被回收。如果您想要在作用域之后保留该引用,可以将其设置为成员变量。


1
更新为引用wayback机器上的副本。 - Andrew Rollings

0

这里是WeakReference的完整(非线程安全)实现示例

ClassA objA = new ClassA();
WeakReference wr = new WeakReference(objA);
// do stuff 
GC.Collect();
ClassA objA2;
if (wr.IsAlive)
    objA2 = wr.Target as ClassA; 
else
    objA2 = new ClassA(); // create it directly if required

WeakReference位于System命名空间中,因此无需包含任何特殊的程序集。


3
这段代码存在竞态条件,对吗?如果在 if (wr.IsAlive)objA2 = wr.Target as ClassA; 之间对象被回收了怎么办? wr.Target (因此 objA2)会变成 null。 - Sebastian Negraszus
在对象被垃圾回收后,目标属性很可能为空。MSDN文档指出使用IsAlive存在竞态条件,但并未明确说明如何解决该问题。http://msdn.microsoft.com/en-us/library/system.weakreference.isalive.aspx - avl_sweden
@avl_sweden:如果想要对弱引用的目标执行任何操作,应该先检索目标,然后检查它是否为 null。如果它不是 null,则可以保证所引用的对象至少在持有新检索到的引用期间存在。IsAlive 属性适用于仅在引用死亡时才感兴趣的代码;这种代码可以检查 Target 是否为 null,但这可能会导致对象被无意中保持存活。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接