Dispose 仍然会被调用。您所做的只是将变量 _client 指向内存中的其他内容(在本例中:null)。_client 最初引用的对象仍将在 using 语句的末尾释放。
运行这个例子。
class Program
{
static Foo foo = null;
static void Main(string[] args)
{
foo = new Foo();
using (foo)
{
SomeAction();
}
Console.Read();
}
static void SomeAction()
{
foo = null;
}
}
class Foo : IDisposable
{
#region IDisposable Members
public void Dispose()
{
Console.WriteLine("disposing...");
}
#endregion
}
将变量设置为 null 不会破坏对象或阻止它被使用。您所做的只是更改变量的引用,而不是更改最初引用的对象。
后期编辑:
关于关于 MSDN 使用参考http://msdn.microsoft.com/en-us/library/yh598w02.aspx和 OP 中的代码以及在我的示例中的代码的评论中的讨论,我创建了一个更简单的代码版本,如下所示.
Foo foo = new Foo();
using (foo)
{
foo = null;
}
(而且,是的,该对象仍然被处置。)
您可以从上面的链接中推断出代码正在被重写,如下所示:
Foo foo = new Foo();
{
try
{
foo = null;
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}
哪个不会处理对象,并且与代码片段的行为不匹配。所以我通过 ildasm 看了一下,我能收集到的最好的结果是原始引用正在被复制到内存中的新地址中。该语句foo = null;
适用于原始变量,但调用.Dispose()
发生在复制的地址上。所以这里看看我是如何相信代码实际上是被重写的。
Foo foo = new Foo();
{
Foo copyOfFoo = foo;
try
{
foo = null;
}
finally
{
if (copyOfFoo != null)
((IDisposable)copyOfFoo).Dispose();
}
}
作为参考,这是 IL 通过 ildasm 的样子。
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 1
.locals init ([0] class Foo foo,
[1] class Foo CS$3$0000)
IL_0000: newobj instance void Foo::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: stloc.1
.try
{
IL_0008: ldnull
IL_0009: stloc.0
IL_000a: leave.s IL_0016
} // end .try
finally
{
IL_000c: ldloc.1
IL_000d: brfalse.s IL_0015
IL_000f: ldloc.1
IL_0010: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0015: endfinally
} // end handler
IL_0016: call int32 [mscorlib]System.Console::Read()
IL_001b: pop
IL_001c: ret
} // end of method Program::Main
我不是靠盯着 ildasm 谋生的,所以我的分析可以归类为买者自负。然而,行为就是这样。