Using statement/keyword in C#

I came across a question “What is use of using in C#” and I decided to write on it. I hope this blog will help you in knowing “using” statement/keyword better.

The Basic Syntax:

1) For one object

using (MyClass objMyClass = new MyClass())

{

//Use objMyClass

}

2) For Multiple objects

using (MyClass objMyClass = new MyClass(),

objMyClass1 = new MyClass())

{

//Use objMyClass and objMyClass1

}

3) Syntax 3 (Not recommended)

MyClass objMyClass = new MyClass()

using (objMyClass)

{

//Use objMyClass

}

// objMyClass can be used out of using block as well

We will see why it is not recommended in this blog later. If I explain it here then you may not follow it without knowing its main use first.

“using” statement can be used in following scenarios.

Scenario 1: Importing namespace

A well known use of “using” keyword is for importing namespace into classes.

Examples:

using System.Collections.Generic;

using System.Linq;

using System.Text;

Scenario 2: Disposing object automatically

If object is delcared in using statement (like shown in syntax 1), that object becomes out of scope and get destroyed as soon as it leaves using block.

In the syntax 1, the care has to be taken that MyClass should implement IDisposable interface. That means, we can’t declare object of the class which do no implement IDisposable.

My MyClass class looks like below:

class MyClass:IDisposable

{

// Track whether Dispose has been called.

private bool disposed = false;

// Pointer to an external unmanaged resource.

private IntPtr handle;

// The class constructor.

public MyClass(IntPtr handle)

{

this.handle = handle;

}

public MyClass()

{

}

public void DisplayName()

{

Console.WriteLine("MyClass\n");

Console.ReadKey();

}

#region IDisposable Members

public void Dispose()

{

// throw new NotImplementedException();

Dispose(true);

// This object will be cleaned up by the Dispose method.

// Therefore, you should call GC.SupressFinalize to

// take this object off the finalization queue

// and prevent finalization code for this object

// from executing a second time.

GC.SuppressFinalize(this);

}

#endregion

// Dispose(bool disposing) executes in two distinct scenarios.

// If disposing equals true, the method has been called directly

// or indirectly by a user's code. Managed and unmanaged resources

// can be disposed.

// If disposing equals false, the method has been called by the

// runtime from inside the finalizer and you should not reference

// other objects. Only unmanaged resources can be disposed.

private void Dispose(bool disposing)

{

// Check to see if Dispose has already been called.

if (!this.disposed)

{

// If disposing equals true, dispose all managed

// and unmanaged resources.

if (disposing)

{

// Dispose managed resources.

// component.Dispose();

}

// Call the appropriate methods to clean up

// unmanaged resources here.

// If disposing is false,

// only the following code is executed.

CloseHandle(handle);

handle = IntPtr.Zero;

}

disposed = true;

}

// Use interop to call the method necessary

// to clean up the unmanaged resource.

[System.Runtime.InteropServices.DllImport("Kernel32")]

private extern static Boolean CloseHandle(IntPtr handle);

// Use C# destructor syntax for finalization code.

// This destructor will run only if the Dispose method

// does not get called.

// It gives your base class the opportunity to finalize.

// Do not provide destructors in types derived from this class.

~MyClass()

{

// Do not re-create Dispose clean-up code here.

// Calling Dispose(false) is optimal in terms of

// readability and maintainability.

Dispose(false);

}

}

To just test if we can declare object of class without having IDisposable interface, try to execute following code:

using (MyClass1 objMyClass1 = new MyClass1())

{

objMyClass1.DisplayName();

}

And here MyClass1 looks like:

class MyClass1

{

public void DisplayName()

{

Console.WriteLine("MyClass\n");

Console.ReadKey();

}

}

You will get following error:

'UsingKeyword.MyClass1': type used in a using statement must be implicitly convertible to 'System.IDisposable'

The reason for not allowing classes without IDisposable interface is:

“using” statement is shotcut to try/catch/finally block, having Dispose method call in finally block.

Thus,

using (MyClass objMyClass = new MyClass())

{

//Use objMyClass

objMyClass.DisplayName();

}

is similar to

MyClass objMyClass = new MyClass();

try

{

objMyClass.DisplayName();

}

finally

{

if (objMyClass != null)

((IDisposable)objMyClass).Dispose();

}

Thus, we get following benefits from “using”:

1. It ensures that using statement calls the Dispose method on the object in the correct way.

2. Within the using block, the object is read-only and cannot be modified or reassigned.

3. The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object.

4. If you declare any un-managed object in using block, you don't need to explicitly dispose that object. Once the block execution is over, the Dispose will be called automatically.

Scenario 3: Taking care of multiple objects at the same time (Syntax 2)

We can pass multiple object of the same type to using statement. We cannot create multiple objects of different types in one using block. Thus if I write syntax 2 as below, then it is invalid.

using (MyClass objMyClass = new MyClass(),

MyClass1 objMyClass1 = new MyClass1())

{

//Use objMyClass and objMyClass1

}

That is the reason, we don’t have to write type name from second object onwards. In below example, we cannot give type of the class name for second object since it is understood that, type will be same as used for first object.

using (MyClass objMyClass = new MyClass(),

MyClass objMyClass1 = new MyClass())

{

//Use objMyClass and objMyClass1

}

Scenario 5: Aliasing to namespaces

// Define an alias for the nested namespace.
    using Project = PC.MyCompany.Project;

Scenario 5: Aliasing to classes

Like aliases to Namespaces we can have aliases to classes as well.

// Using alias for a class.
using AliasToMyClass = NameSpace1.MyClass;   
 
 

Answer to why Syntax 3 is not recommended

Wait! Don’t scroll to look at syntax 3, to help you to understand it better, I have put it below J

MyClass objMyClass = new MyClass()

using (objMyClass)

{

//Use objMyClass

}

// objMyClass can be used out of using block as well

As we know by now, unmanaged resources referenced/used by object get destroyed as soon as it leaves “using” block. So even object is accessible after using block, it may not have access to unmanaged resources and if we try to access object, it may be risky to use it because object may not be available in fully initialized state. For this reason, it is generally better to instantiate the object in the using statement and limits its scope to the using block.

 

References:

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

http://msdn.microsoft.com/en-us/library/system.idisposable.dispose%28VS.71%29.aspx

Comments