C# 通过设置为null进行处理?

C# 通过设置为null进行处理?,c#,.net,idisposable,C#,.net,Idisposable,我知道用传统方式处理IDisposable的技术。例如,在windows服务的OnStop()方法中,我关闭了消息队列客户端: if (client != null) { client.Dispose(); } 今天我第一次看到一个人这样做: using (client) { client = null; } 在他的“使用”中到底发生了什么,或者他是

我知道用传统方式处理IDisposable的技术。例如,在windows服务的OnStop()方法中,我关闭了消息队列客户端:

        if (client != null)
        {
            client.Dispose();
        }
今天我第一次看到一个人这样做:

        using (client)
        {
            client = null;
        }
在他的“使用”中到底发生了什么,或者他是否正确处理了?

退出

using (client)
{
}
client.Dispose()
会自动为您调用。
我认为应该从该代码中调用
client=null


请记住,要使用
using(object)
对象应实现
IDisposable
接口。

using(){}语句获取引用变量的副本,因此此
null
赋值无效

在我看来,它一点效果都没有。由于客户机被设置为null,所以即使实际的对象仍在内存中,也不会被任何变量引用(稍后会被垃圾收集,但使用的意义何在?)。

您的
使用基于
的同事的代码会起作用,但可以说是杀伤力过大

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();
  }
}
(并非所有情况下都如此,因为需要考虑值类型和显式接口实现)

就个人而言,我只会在可能的情况下(即在最初分配客户机的代码中)对整个事情使用
use

有一次我可能会用这是一个懒惰的:

using(client as IDisposable) { client = null; } // dispose if needed
i、 e.
client
是我无法控制的,我不确定它是否实现了
IDisposable
,但如果实现了,我需要释放它。

如果“client”的范围扩展到了“using”块之外,那么编写的代码将确保在控件离开“using”之前释放“client”块,则对新失效的“客户端”对象的引用将被销毁。如果它是一个字段,则清空对它的引用可能很重要,如果它是一个附加事件的属性,则可能很关键

我的猜测是,“客户机”是一个字段或属性,“使用”代码的作者认为它比Marc Gravell给出的版本更简洁。我同意作者的观点,代码是简洁的,但我建议更简洁、更清晰的是定义一个通用的“Zap”例程,该例程通过引用接受IDisposable,使用Interlocked.Exchange读取并将其置零,如果它不为null,则对其进行处理。在这种情况下,“使用”语句将替换为:

Zap(ref client); Zap(参考客户);
它的优点是更简洁,同时几乎可以肯定更清晰。

但也无害(它不会干扰对dispose的调用)同意在第二种情况下,必须再次复制指针。将Dispose隐式地放在Dispose本身中是没有意义的。在任何情况下,在重新进入dispose时,您还需要进行null检查以避免null ref异常。@Martijn-无害?通常情况下,如果您想推迟处置
客户端
,则不会这样做。罕有但有可能。@Henk Holterman:不太罕有——这样的推迟对构造函数来说是一种很好的模式。为什么要否决投票?如果我说错了什么,请解释一下,这样我就可以更正或删除我的答案……不,没有什么特别的错误;只有一个用户投了几票反对票;与此线程中涉及的任何用户都没有紧密联系。只是奇怪的是,真的。顺便说一句,我认为可以提高“使用”的可用性的一件事是,可以显式地将“shadow变量”设置为null,这样就不会处理对象,或者有一个版本的“使用”只会在出现错误时处理。例如,构造函数可以“使用”要构造的对象的字段,然后在返回之前决定“保留”这些字段。可以使用try/finally块而不是“using”,但它们更详细,更不清晰。@supercat IMO该场景已经相当复杂了-最好明确地描述它,并了解正在发生的事情(即,我对
try
/
finally
感到满意)我只是再次查看了代码,并认为我理解了它的用途——如果“客户机”是一个字段或属性,那么它的生命周期可能不局限于“使用”块。在某些情况下,在调用Dispose之前,可能需要清除包含对象引用的字段或属性。这里显示的“使用”代码比显式创建临时变量更简洁,尽管更好的方法是使用“Zap”例程来实现这一目的。