代码之家  ›  专栏  ›  技术社区  ›  psulek

关于IDisposable对象的using语句-调用Dispose方法的延迟

  •  7
  • psulek  · 技术社区  · 14 年前

    正如所描述的 article ,关于在IDisposable对象上使用的用法,它说了一个有趣的词:

    …使用block时,Dispose方法将在块结束后自动调用。(可能不是立即的;这取决于CLR。)

    它可能不是立即的;它取决于CLR ". 有谁能提供更多的细节吗?因为我们有一些奇怪的情况,在使用(new MyDisposable()){…}的代码时,在块}结束之后 不是 立即对MyDisposable实例调用Dispose方法,但一段时间后。

    谢谢你的回复!

    4 回复  |  直到 14 年前
        1
  •  6
  •   vcsjones    14 年前

    我对这句话有点怀疑,认为它们意味着别的东西(也许是垃圾收集)。using语句只是try/finally块的语法糖,finally块调用dispose。鉴于此C#:

    using (var fs = new FileStream("C:\\blah.txt", FileMode.CreateNew))
    {
        fs.WriteByte(7);
    }
    

    IL看起来是这样的:

    //snipped
    L_000e: nop 
    L_000f: ldstr "C:\\blah.txt"
    L_0014: ldc.i4.1 
    L_0015: newobj instance void [mscorlib]System.IO.FileStream::.ctor(string, valuetype [mscorlib]System.IO.FileMode)
    L_001a: stloc.0 
    L_001b: nop 
    L_001c: ldloc.0 
    L_001d: ldc.i4.7 
    L_001e: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
    L_0023: nop 
    L_0024: nop 
    L_0025: leave.s L_0037
    L_0027: ldloc.0 
    L_0028: ldnull 
    L_0029: ceq 
    L_002b: stloc.1 
    L_002c: ldloc.1 
    L_002d: brtrue.s L_0036
    L_002f: ldloc.0 
    L_0030: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    L_0035: nop 
    L_0036: endfinally 
    L_0037: nop 
    L_0038: nop 
    L_0039: ret 
    .try L_001b to L_0027 finally handler L_0027 to L_0037
    

    http://msdn.microsoft.com/en-us/library/aa664736.aspx

        2
  •  9
  •   Darin Dimitrov    14 年前
    using (SomeDisposableResource resource = new SomeDisposableResource())
    {
        // TODO: use the resource
    }
    

    相当于:

    SomeDisposableResource resource = new SomeDisposableResource();
    try
    {
        // TODO: use the resource
    }
    finally
    {
        if (resource != null)
        {
            ((IDisposable)resource).Dispose();
        }
    }
    

    所以,由你来做结论。一切都取决于你如何定义 立即的 try 块和资源的处理,但是当它被包装在 finally 阻止-保证 Dispose

        3
  •  1
  •   usr-local-ΕΨΗΕΛΩΝ    14 年前

    奇怪。。。很奇怪。。。

    这篇文章可能是错的。using语句已编译 确切地

    MyDisposableObject obj = new MyDisposableObject()
    try
    {
        obj.Use();
    }
    finally
    {
        if (obj!=null) obj.Dispose();
    }
    

    Dispose方法在 finally 块,不像析构函数/ Finalize 在收集之前调用但由GC决定的方法。

    在某时 很少

    它是 重要的

    public void Log(string message)
    {
        using(StreamWriter sw = new StreamWriter(File.Append(path)))
        {
            sw.WriteLine(message);
        }
    }
    public static void Main()
    {
        Log("Hello");
        Log("World");
    }
    

    这个 Dispose Log 用一个 打开文件 ,从而导致 IOException 马上!

        4
  •  0
  •   Guffa    14 年前

    using 例如,语句 this article 也就是说 这样阻止:

    using (Font font1 = new Font("Arial", 10.0f)) {
      byte charset = font1.GdiCharSet;
    }
    

    实现方式如下:

    Font font1 = new Font("Arial", 10.0f);
    try {
        byte charset = font1.GdiCharSet;
    } finally {
      if (font1 != null) {
        ((IDisposable)font1).Dispose();
      }
    }
    

    Dispose 方法将在 使用 封锁。