How effectively release memory of unmanaged resource in .NET? - ablealias/asp.net GitHub Wiki

The common language runtime's (CLR) garbage collector reclaims the memory used by managed objects, but types that use unmanaged resources implement the IDisposable interface to allow the memory allocated to these unmanaged resources to be reclaimed. When you finish using an object that implements IDisposable, you should call the object's IDisposable.Dispose implementation. You can do this in one of two ways:

  • With the C# using statement.
  • By implementing a try/finally block.

The using statement

The using statement in C# simplify the code that you must write to create and clean up an object. The using statement obtains one or more resources, executes the statements that you specify, and automatically disposes of the object. However, the using statement is useful only for objects that are used within the scope of the method in which they are constructed.

When the lifetime of an IDisposable object is limited to a single method, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

The following example uses the using statement to create and release a System.IO.StreamReader object.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      Char[] buffer = new Char[50];
      using (StreamReader s = new StreamReader("File1.txt")) {
         int charsRead = 0;
         while (s.Peek() != -1) {
            charsRead = s.Read(buffer, 0, buffer.Length);
            //
            // Process characters read.
            //   
         }
         s.Close();    
      }

   }
}

Note that although the StreamReader class implements the IDisposable interface, which indicates that it uses an unmanaged resource, the example doesn't explicitly call the StreamReader.Dispose method. When the C# compiler encounters the using statement, it emits intermediate language (IL) that is equivalent to the code that explicitly contains a try/finally block.

The C# using statement also allows you to acquire multiple resources in a single statement, which is internally equivalent to nested using statements. The following example instantiates two StreamReader objects to read the contents of two different files.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      Char[] buffer1 = new Char[50], buffer2 = new Char[50];
      
      using (StreamReader version1 = new StreamReader("file1.txt"),
                          version2 = new StreamReader("file2.txt")) {
         int charsRead1, charsRead2 = 0;
         while (version1.Peek() != -1 && version2.Peek() != -1) {
            charsRead1 = version1.Read(buffer1, 0, buffer1.Length);
            charsRead2 = version2.Read(buffer2, 0, buffer2.Length);
            //
            // Process characters read.
            //
         }
         version1.Close();
         version2.Close();
      }
   }
}