弱引用的理解

20

我想创建包含所有ViewModel的字典。

   public static Dictionary<string, WeakReference> vmCollection = new Dictionary<string, WeakReference>();

像这样添加

 vmCollection.Add(name, new WeakReference(viewModel));

这样调用所需的方法:

((vmCollection[viewModel].Target) as BaseViewModel).NewMessage(message);

我需要将它维护为WeakReference吗?如果我不将其维护为WeakReference,可能会有什么后果。


4
访问对象之前,请不要忘记检查它是否存活 - 在WeakReference中使用IsAlive。 - Ventsyslav Raikov
如果您正在寻找实现消息传递类型解决方案,那么您是否看过Prism中的EventAggregator? - slugster
谢谢slugster。我想自己实现它,以避免任何依赖关系... - Learner
2个回答

32
不使用WeakReference的唯一后果是,字典中的引用将阻止View Model实例被垃圾回收。WeakReference允许垃圾回收(假设没有其他实体引用)。当一个项目没有对它的引用时,它就可以进行垃圾回收。WeakReference不会创建可计数的引用,因此你可以保留对它的某种引用,但如果你的WeakReference是唯一剩下的引用,它仍然可以被垃圾回收。是否需要它真的取决于你的View Models的生命周期。如果它们需要处理或以其他方式“放手”,那么你可能需要使用WeakReference或公开一种从字典中删除引用的方法。正如我在评论中提到的,与明确处理相关对象的生命周期相比,我倾向于避免使用WeakReference。也就是说,在相关点上没有足够的生命周期可见性时,它们非常有用。我认为在你的情况下,由于这些都很可能在UI层中,因此应该尽量不使用它们。

这里有一个关于该主题的资源:

从上述MSDN链接中提取的指南:

只有在必要时才使用长弱引用,因为对象在完成后状态是不可预测的。

避免使用弱引用来引用小对象,因为指针本身可能与对象一样大或更大。

避免将弱引用作为内存管理问题的自动解决方案。相反,为处理应用程序对象开发一个有效的缓存策略。

我认为最后一个指南点适用于您的情况。


非常感谢,Adam。如果我为了更安全起见使用它,会有任何额外的开销吗? - Learner
2
@RaoBHavik 开销将是 WeakReference 对象实例本身的成本,以及需要不断检查所引用的对象是否仍然可用(显然,自上次使用以来它可能已被回收)。我总是倾向于明确处理对象的生命周期而不是使用它们,但有时您只是没有生命周期的可见性,因此它们可以证明是有用的。我认为在您的情况下,您应该具有可见性,因此应该尽量避免使用它们。 - Adam Houldsworth

0

我采用了稍微不同的方法。

对于这个示例,我只有一个单个实例,但我相信它很容易扩展到多个实例...

因此,在我的类上,我创建了以下操作(如果需要返回某些内容,也可以是一个Func)。就我的例子而言,我只是在传递一个异常:

private  static Action<Exception> StaticAccessorToInstanceMethod { get; set; }

我想调用的实例方法是:

public void HandleExceptionDetails(Exception e)
{
    // Content of the method on the instance
}

然后我在我的构造函数中有这个:

StaticAccessorToInstanceMethod = this.HandleExceptionDetails;

并在析构函数中添加以下内容:

StaticAccessorToInstanceMethod = null;

如果你正在处理多个实例,那么构造函数和析构函数的代码会有所不同。

然后静态方法只是调用实例方法:

public static void HandleGeneralException(Exception ex)
{    
     StaticAccessorToInstanceMethod(result);
}

我忽略了防御性逻辑。


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