我知道以传统方式处理IDisposable的技术。比如,在Windows服务的OnStop()方法中我关闭了消息队列客户端:
if (client != null)
{
client.Dispose();
}
今天我第一次看到一个人这样做:
using (client)
{
client = null;
}
他的“使用”内部究竟发生了什么,或者他是否正确处置?
答案 0 :(得分:6)
using(){}
语句获取引用var的副本,因此使用null
进行此分配无效。
答案 1 :(得分:4)
您的基于using
的同事的代码会起作用,但可能有点矫枉过正;
using(client) {
client = null;
}
基本上是:
{ // scope here to denote that 'tmp' is not defined outside this scope
var tmp = client;
try {
client = null;
} finally {
if(tmp != null) tmp.Dispose();
}
}
(不是相当,在所有情况下,因为有值类型和显式接口实现需要考虑)。
就个人而言,我只会在可能的情况下使用using
(即在最初分配客户端的代码中)。
有一次我可能会使用这个是懒惰的:
using(client as IDisposable) { client = null; } // dispose if needed
即。 client
是我无法控制的,我不确定它是否实现IDisposable
,但如果确实如此,我需要释放它。
答案 2 :(得分:3)
退出
using (client)
{
}
系统会自动为您调用 client.Dispose()
在我看来,应该从该代码中调出client = null
请记住,要使用using(object)
,对象应实现IDisposable
接口。
答案 3 :(得分:0)
对我而言,它看起来根本没有效果。由于客户端设置为null,因此即使实际对象仍然在内存中,也没有引用任何变量引用,因为它不会被任何变量引用(稍后将对其进行垃圾回收,但是使用的重点是什么? )。
答案 4 :(得分:0)
如果“client”的范围扩展到“using”块之外,就像它所看到的那样,写入的代码将确保在控制离开“using”块之前“客户端”被释放,并且引用新发布的“客户”对象将被销毁。如果它是一个字段,则取消对它的引用可能很重要,如果它是一个附加事件的属性,则可能是关键的。
我的猜测是“客户”是一个字段或属性,“使用”代码的作者认为它比Marc Gravell给出的版本更简洁。我会授予作者代码简洁,但会建议更简洁,更清晰的是定义一个通用的“Zap”例程,它接受一个IDisposable 引用,使用Interlocked.Exchange来读取并将其置零,如果它不为null则处置它。在这种情况下,“using”语句将替换为:
Zap(ref client);
这有利于更简洁,但几乎肯定更清晰。