using关键字动态 [英] Dynamics of the using keyword

查看:215
本文介绍了using关键字动态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的代码:

// 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆