using关键字动态 [英] Dynamics of the using keyword
问题描述
考虑下面的代码:
// module level declaration
Socket _client;
void ProcessSocket() {
_client = GetSocketFromSomewhere();
using (_client) {
DoStuff(); // receive and send data
Close();
}
}
void Close() {
_client.Close();
_client = null;
}
由于该代码调用关闭()
方法,它关闭 _client
插座,将其设置为空
,同时还在里面的'使用'块,到底发生了什么在幕后?是否插座真正关闭?有没有副作用?
Given that that the code calls the Close()
method, which closes the _client
socket and sets it to null
, while still inside the `using' block, what exactly happens behind the scenes? Does the socket really get closed? Are there side effects?
P.S。这是一个用C#3.0在.NET MicroFramework,但我想在C#语言,应该相同的功能。我之所以要问的是,偶尔,很少,我用完了套接字(这是在.NET MF设备非常珍贵的资源)的。
P.S. This is using C# 3.0 on the .NET MicroFramework, but I suppose the c#, the language, should function identically. The reason i am asking is that occasionally, very rarely, I run out of sockets (which is a very precious resource on a .NET MF devices).
推荐答案
处置仍将被调用。所有你做的是指向变量_client别的记忆的东西(在这种情况下:零)。到仍然会设置在using语句的结尾是_client intially所指的对象。
Dispose will still be called. All you are doing is pointing the variable _client to something else in memory (in this case: null). The object that _client intially referred to will still be disposed at the end of the using statement.
运行这个例子。
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不会破坏对象或防止它被放置在由使用。所有你做的是改变变量的基准,在不改变原来所引用的对象。
Setting the variable to null is not destroying the object or preventing it from being disposed by the using. All you are doing is changing the reference of the variable, not changing the object originally referenced.
后期编辑:
对于从约MSDN的使用参考 http://msdn.microsoft .COM / EN-US /库/ yh598w02.aspx 并在OP和在我的例子中的代码,我创建像这样的代码的简化版本。
Regarding a discussion from the comments about MSDN's using reference http://msdn.microsoft.com/en-us/library/yh598w02.aspx and the code in the OP and in my example, I created a simpler version of the code like this.
Foo foo = new Foo();
using (foo)
{
foo = null;
}
(是的,对象仍然得到处理。)
(And, yes, the object still gets disposed.)
您可以从上面的代码被改写这样的链接推断:
You could infer from the link above that the code is being rewritten like this:
Foo foo = new Foo();
{
try
{
foo = null;
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}
这不会处理的对象,而那不匹配的代码片段的行为。所以我看了看它通过ILDASM,我可以收集最好的是,原来的基准被复制到内存中的新地址。声明富= NULL;
适用于原始变量,但调用 .Dispose()
正在发生的复制地址。因此,这里是一看我怎么相信代码实际上是被改写。
Which would not dispose the object, and that does not match the behavior of the code snippet. So I took a look at it through ildasm, and the best I can gather is that the original reference is being copied into a new address in memory. The statement foo = null;
applies to the original variable, but the call to .Dispose()
is happening on the copied address. So here is a look at how I believe the code is actually being rewritten.
Foo foo = new Foo();
{
Foo copyOfFoo = foo;
try
{
foo = null;
}
finally
{
if (copyOfFoo != null)
((IDisposable)copyOfFoo).Dispose();
}
}
有关的参考,这是什么IL看起来像通过ILDASM。
For reference, this is what the IL looks like through 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盯着,所以我的分析可以被列为买者自负。但是,行为的就是这样。的
这篇关于using关键字动态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!