完成后,是否应该将所有对象设置为null(Nothing在VB.NET中)?
我理解在.NET中必须处理实现IDisposable接口的任何对象实例以释放一些资源,尽管对象在处理之后仍然可以是某种东西(因此isDisposed表单中的属性),所以我认为它仍然可以驻留在记忆中还是至少部分?
我也知道当一个对象超出范围时,它会被标记为收集准备好下一次垃圾收集器的传递(虽然这可能需要时间).
因此,考虑到这一点,将其设置为null加速系统释放内存,因为它不必解决它不再在范围内并且它们是否有任何不良副作用?
MSDN文章从未在示例中执行此操作,目前我这样做是因为我无法看到它的危害.但是我遇到了各种意见,所以任何评论都是有用的.
作为一名C++开发人员,Java和.NET中缺少RAII(资源获取是初始化)一直困扰着我.清理的责任从班级作者转移到其消费者(通过try finally.NET的using构造)这一事实似乎显然是劣等的.
我明白为什么在Java中不支持RAII,因为所有对象都位于堆上,而垃圾收集器本身并不支持确定性破坏,但在.NET中引入了values-types(struct)我们有(看似) RAII的完美候选人.在堆栈上创建的值类型具有明确定义的范围,并且可以使用C++析构函数语义.但是,CLR不允许值类型具有析构函数.
我的随机搜索发现了一个论点,如果一个值类型被装箱,它就属于垃圾收集器的管辖范围,因此它的破坏变得不确定.我觉得这个论点不够强大,RAII的好处足以说明带有析构函数的值类型不能被装箱(或用作类成员).
简而言之,我的问题是:为了将RAII引入.NET,是否有任何其他原因无法使用值类型?(或者您认为我关于RAII明显优势的论点有缺陷吗?)
编辑:我必须没有明确表达这个问题,因为前四个答案已经错过了重点.我知道关于Finalize其不确定性的特点,我知道的using结构,我觉得这两个选项都逊色于RAII.using是一个阶级的消费者必须记住的另一件事(有多少人忘了把它StreamReader放在一个using街区?).我的问题是关于语言设计的哲学问题,为什么它是这样的,它可以改进吗?
例如,对于通用的确定性可破坏的值类型,我可以使using和lock关键字冗余(可以通过库类实现):
public struct Disposer<T> where T : IDisposable
{
T val;
public Disposer(T t) { val = t; }
public T Value { get { return val; } }
~Disposer() // Currently illegal
{
if (val != default(T))
val.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
我忍不住以我曾经看过的apropos报价结束,但目前无法找到它的起源.
当我的冷死手超出范围时,你可以采取我的确定性破坏.- 匿名
如果我使用EventWaitHandle(或AutoResetEvent,ManualResetEvent)来同步线程之间然后做我需要调用Close()或Dispose()方法对事件处理的时候,我用它做什么?
EventWaitHandle继承自WaitHandle,实现IDisposable.如果我没有IDisposable在包含任何类的任何类上实现,FxCop会抱怨EventWaitHandle.所以这表明我确实需要打电话给它.
但是,这些MSDN用法示例都没有调用Dispose()或Close():
http://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle(VS.80).aspx http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent( VS.80).aspx http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(VS.80).aspx
这只是微软无视自己建议的一个例子吗?
有很多问题要求如何检测IDisposable对象泄漏.似乎答案是"你不能".
我刚刚用最琐碎的测试用例检查过,FxCop 10.0没有这样做,带有MSVS2010的ReSharper 4没有这样做.
这对我来说似乎不对,比C中的内存泄漏更糟糕(至少我们已经建立了检测工具).
我在想:是否有可能使用反射和其他模糊的高级技术,我可以在运行时注入一个检查,在终结器中查看是否Dispose已被调用?
WinDBG + SOS的魔术技巧怎么样?
即使没有现成的工具,我也想知道这在理论上是否可行(我的C#不是很尖锐).
想法?
注意这个问题的标题可能会产生误导.这里真正的问题应该是一个是否IDisposable对象已Disposed()正确.由于我认为这是一个错误,因此由GC处理并不重要.
编辑:解决方案:.NET Memory Profiler完成工作.我们只需要GC.Collect()在程序结束时发送几个垃圾邮件,以使我们的探查器能够正确地获取统计数据.
.net ×4
c# ×3
destructor ×1
idisposable ×1
memory-leaks ×1
null ×1
raii ×1
struct ×1
value-type ×1
vb.net ×1