我说我的课程定义为:
class MyWrapper<T> where T : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChange(String propname)
{
handlePropertyChanged(this, new PropertyChangedEventArgs(propname));
}
private void handlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(sender, e);
}
}
private T _backing;
public MyWrapper(T backing)
{
_backing=backing;
_backing.PropertyChanged+=handlePropertyChanged;
}
...Reasons for wrapping the class...
}
此类在后备对象上的PropertyChanged事件上设置委托。 根据我的理解,这个委托有一个指向MyWrapper实例的指针。这是否意味着MyWrapper的实例的生命周期不会短于烘焙对象?
如果是这样,有办法解决这个问题吗?
答案 0 :(得分:1)
是的,另一个属性对事件句柄的引用会阻止MyWrapper类实例被垃圾回收。只有当释放对处理程序的所有引用时(例如,当这些实例也符合GC条件时),才能从内存中释放MyWrapper实例。
此问题类似于之前发布的问题:Do event handlers stop garbage collection from occuring?
修改强>
要回答您对该代表的评论,请将handlePropertyChanged
指定为backing
的代理,该代理会创建对MyWrapper
的外部引用。因此,在删除该引用之前,MyWrapper
将不会被GC。
有几种方法可以解决这个问题:
答案 1 :(得分:1)
如果你真的想保留一个没有阻止GC的引用,那么看一下弱引用。这些允许您保持对对象的引用,只要它存在(您总是需要明确检查对象是否仍然存在并提取“真实”,强引用)。
对于代表,WeakEvent
是合适的。
但是,我也建议采用另一种方法。如果事件处理程序确实没有做任何事情(如示例代码中所示),则可以完全跳过它,并像这样声明PropertyChanged
:
public event PropertyChanged
{
add { _backing.PropertyChanged += value; }
remove { _backing.PropertyChanged -= value; }
}
或者,如果处理程序很重要(例如,它转换输入等),您可以考虑使用一个显式的dispose模式来取消注册任何事件处理程序:
public void Dispose() { _backing.PropertyChanged -= handlePropertyChanged; }
完成使用包装器对象后,只需调用Dispose
(或者,如果有固定范围,请使用using
)。这是简化的 - 一个适当的配置模式有点复杂,但如果你不处理非托管资源则不是必需的。