C# Using 语句: Dispose and IDisposable

这些C#示例项目会展示using语句的使用。他们处理IDisposable类型。

Using块用于管理资源

从概念上来说,通过指定资源的使用范围来保护整个系统的资源。using语句与实现IDisposable的类型相结合。

Example

刚开始,这个小项目定义了一个叫做SystemResource的类。这个类实现了IDisposable接口和所需的Dispose方法。在Main方法中,我们在using语句中包装了SystemResource实例。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Drawing;
 6 using System.Windows.Forms;
 7 
 8 namespace UsingDemo
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             // Use using statement with class that implements Dispose.
15             using (SystemResource resource = new SystemResource())
16             {
17                 Console.WriteLine(1);
18             }
19             Console.WriteLine(2);
20         }
21     }
22 
23     class SystemResource : IDisposable
24     {
25         public void Dispose()
26         {
27             // The implementation of this method not described here.
28             // ... For now, just report the call.
29             Console.WriteLine(0);
30         }
31     }
32 }

 

 当项目执行的时候会发生什么呢?

首先,SystemResource实例在托管堆上被分配。接下来,“1”被输出;第三,“0”被输出,因为调用了Dispose方法。最后,“2”被打印出来。

然后:如展示的那样,当控制流退出using块时,立即调用Dispose方法。

Using嵌套:

可以一个接一个地嵌套多层using语句。在这种情况下,不需要使用任何花括号。在第二个或更多层次的using语句中,你可以使用在前面的using语句中声明的变量。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Drawing;
 6 using System.Windows.Forms;
 7 
 8 namespace UsingDemo
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             // Use using statement with class that implements Dispose.
15             using (SystemResource resource1 = new SystemResource())
16             using (SystemResource resource2 = new SystemResource())
17             {
18                 Console.WriteLine(1);
19             }
20             Console.WriteLine(2);
21         }
22     }
23 
24     class SystemResource : IDisposable
25     {
26         public void Dispose()
27         {
28             // The implementation of this method not described here.
29             // ... For now, just report the call.
30             Console.WriteLine(0);
31         }
32     }
33 }

 

 最常见的与using一起使用的类型是那些已经在.NET框架中定义好的类型。这些类型包括StreamReader, StreamWriter, BinaryReader, BinaryWriter, 甚至是 DataTable。

为此,只需在using语句中为类型使用资源获取表达式。你不需要实现任何接口。很多类型已经实现了Dispose方法。

Performance性能

using语句会影响到性能。在一些地方,using语句不是必要的,因为这些对象不会接触到托管资源。我们进一步探讨这一点。我们在不需要using语句的对象上使用using语句进行基准测试。

首先:这个函数版本有多层using语句,这个函数接收一个byte数组,这个数组是托管类型。

注:所有的流都是从byte数组创建的,所以它们不能链接到像磁盘这样的非托管资源。

 

Version with using statements: C#

static byte[] Decompress1(byte[] gzip)
{
    using (MemoryStream mem = new MemoryStream(gzip))
    using (GZipStream stream = new GZipStream(mem,
    CompressionMode.Decompress))
    {
    const int size = 4096;
    byte[] buffer = new byte[size];
    using (MemoryStream memory = new MemoryStream())
    {
        int count = 0;
        do
        {
        count = stream.Read(buffer, 0, size);
        if (count > 0)
        {
            memory.Write(buffer, 0, count);
        }
        }
        while (count > 0);
        return memory.ToArray();
    }
    }
}

下面,我们看一个没有三层using语句块嵌套的版本。这是安全的,因为它们不是使用非托管资源创建的。在中间语言中,这消除了许多复杂性和三个try-finally构造。

Version without using statements: C#

static byte[] Decompress2(byte[] gzip)
{
    GZipStream stream = new GZipStream(new MemoryStream(gzip),
    CompressionMode.Decompress);
    const int size = 4096;
    byte[] buffer = new byte[size];
    MemoryStream memory = new MemoryStream();
    int count = 0;
    do
    {
    count = stream.Read(buffer, 0, size);
    if (count > 0)
    {
        memory.Write(buffer, 0, count);
    }
    }
    while (count > 0);
    return memory.ToArray();
}
C# program that benchmarks using statements

using System.IO;
using System.IO.Compression;

class Program
{
    const int _max = 200000;
    static void Main()
    {
    byte[] array = File.ReadAllBytes("C:\\t2\\_default.gz");
    Decompress1(array);
    Decompress2(array);

    for (int i = 0; i < _max; i++)
    {
        Decompress1(array);
    }
    for (int i = 0; i < _max; i++)
    {
        Decompress2(array);
    }
    }
}
Benchmark results

Decompress1: Has 3 using statements.
Decompress2: Has 0 using statements.

Decompress1 Memory: 4852 K, 4804 K, 4852 K
Decompress2 Memory: 4768 K, 4752 K, 4784 K

结果:我们看到了试验结果。每个函数耗费了相同数量的时候去执行(9s)。这主要是依据文件大小。然而,Decompress2函数使用了更少的内存消耗。

因此:不必要的using语句最终浪费了内存。这可以通过方法大小膨胀和复杂性增加来解释。

概述:using语句为调用IDisposable接口实现中的Dispose方法提供了一个语法糖。本文没有描述Dispose的有用实现。

https://thedeveloperblog.com/using

using实质
   
在程序编译阶段,编译器会自动将using语句生成为try-finally语句,并在finally块中调用对象的Dispose方法,来清理资源。所以,using语句等效于try-finally语句,例如:

using (Font f2 = new Font("Arial", 10, FontStyle.Bold))
{
     font2.F();
}

被编译器翻译为:
     Font f2 = new Font("Arial", 10, FontStyle.Bold);
  try
  {
      font2.F();

  }
  finally
  {
      if (f2 != null) ((IDisposable)f2).Dispose();
  }

https://www.cnblogs.com/xiaobiexi/p/6179127.html

posted @ 2022-08-06 22:59  chenlight  阅读(518)  评论(0编辑  收藏  举报