假设我有一个带有对象字段的类。调用Dispose()时,我想清除对该对象的引用。私有字段只能设置一次,所以理想情况下我希望它只是readonly,但如果它是readonly,当我尝试在Dispose()期间释放对象的引用时,会出现编译时错误。理想情况下,我希望安全处置并将_value字段标记为只读。这是可能的还是必要的?
public class Foo : IDisposable
{
public Foo(object value)
{
_value = value;
}
public object Value { get { return _value; } }
private readonly object _value;
public void Dispose()
{
//Cleanup here
_value = null // causes compile time error
}
}
答案 0 :(得分:4)
将引用设置为null实际上并不执行任何操作。垃圾收集器将在不再引用该对象时清理该对象,在这种情况下,因为您在Dispose方法中执行此操作,可能是Foo的实例将不再具有对它的任何引用,并且时机可能没有意义。通常,您实现Dispose模式,因为您的类型具有一个本身实现IDisposable的类(在这种情况下类型为Object,它不实现IDisposable),或者您有非托管资源,您希望确定性地发布。您可以找到Dispose模式here的说明。请注意,如果您创建一个实现IDisposable类型的只读成员变量,您可以在Dispose方法中调用该对象上的Dispose方法:
public class SomeClass : IDisposable
{
private Boolean mDisposed;
private readonly MemoryStream mStream = new MemoryStream(); // Could be any class that implements IDisposable
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(Boolean disposing) {
if (disposing & !mDisposed) {
mStream.Dispose(); // Could and should call Dispose
mDisposed = true;
}
return;
}
}
这是有效的,因为readonly性质是对象的引用,而不是对象本身。
答案 1 :(得分:3)
即使有可能,也没有必要。
Dispose通常用于清理非托管资源,尽管该规则可能有例外(请注意注释)。但是,在这种情况下,您应该允许垃圾收集器完成其工作。一旦认为对象没有活动根,它将不确定地运行。在正常情况下,您不需要采取措施强制它。只需在适当限制的范围内编写包含对象的代码,就可以了。
答案 2 :(得分:1)
这不是必要的,也不是正确的。想要在你的问题中做你想问的事情似乎表明你在某个地方访问被处置的对象,这是错误的。
您应该实现IsDisposed
(btw是standard Dispose pattern的一部分)并首先检查它,而不是尝试按照您的要求进行操作。
正如其他人所说,Dispose模式旨在释放非托管资源。
答案 3 :(得分:0)
这是一篇较旧的帖子,但我经常面对同样的问题,因为我取消订阅了我订阅的对象。
我在处理期间执行此取消订阅,因为这些对象的活动时间比此对象长,并且代理的实现方式意味着发布者使订阅者保持活跃,而不是像我们想象的那样。
但是,当您取消订阅活动时,您自然倾向于想要清除对发布者的引用,这实际上并不是什么大问题。我建议你保持'readonly'约束,因为它使规则更清晰,代码在对象仍然存活时更健壮。如果这意味着您在处置后与参考坐在一起,那就没关系,因为该对象现在是收藏。