Using Statement In C#

Introduction

 
This post explains how to utilize the using keyword.
 

using keyword

 
There are three major ways to use the using keyword,
  • Using Directive
  • Using Static Directive
  • Using Statement
Here we will discuss the Using Statement.
 

Using Statement

  • What is it?

    • A statement which contains the 'using' keyword, then it is called using a statement.

  • What it does:

    • Specifies the scope or boundary of the use of a resource object (normally use curly braces, {}).
    • After the end of a scope, it's called Dispose method.
    • Note: If an exception occurs between this scope, then it's also called Dispose method (for more details please have a look in the 'How to work' section).
    • The dispose method will free the resource object because it's no longer needed.
    • In summary, every object has a life cycle (life cycle means creation and destroying the object). After destroying the object we have to release the destroyed object resources. It is done by CLR and you can control it by using a statement.

  • Why do we need it?

    • .NET framework is designed with an automatic memory or resource management feature which disposes, releases, or frees the object automatically.

      • This process is completed through non-deterministic mode whenever the Common Language Runtime (CLR) is decided upon to perform garbage collector (GC).

        • Decision
          If you want to control this memory management, then we need to use a using statement. This time GC will be done by us, rather than CLR.


    • There are mainly two types of memory resources,

      • Managed Resource

        • Created by managed objects.
        • Managed by CLR.
        • Example: int, string bool etc variables (those are all in .NET scope).
        • Decision
          These manage resources are released by CLR, but if we want to release by ourselves then we need a using statement.

      • Unmanaged Resource

        • Created by unmanaged objects.
        • Not managed by CLR.
        • Example: third party libraries such as file streams, network connection, device context, database connection objects.
        • Decision
          These unmanaged resources are resource-intensive, so we have to release as quickly as possible. We can do this with a using statement.
      • Note
        Using statement is used for unmanaged resource because managed resource are released by CLR automatically.

    • Simply put, .NET framework provides a using statement for memory clean-up activities.

  • How to use?

    • The using statement takes only one parameter, a resource that is represented by a class or stack.
      1. //    
      2. // using statement syntax    
      3. //    
      4. using(resource, it can be a class object)     
      5. {    
      6.     // body     
      7. }     
      8.     
      9. // more specific syntax    
      10. using (<ClassName> <VariableName> = new <ClassName>())    
      11. {    
      12.    // body    
      13. }    
      14. //    
      15. // using statement example    
      16. //    
      17.     
      18. // Create a Car Class, whose has a property Name    
      19. public class Car    
      20. {    
      21.     public string Name { getset; } = "Super Car";    
      22. }    
      23.     
      24. // Call Car class from Main method     
      25. class Program    
      26. {    
      27.     static void Main(string[] args)    
      28.     {    
      29.         // here carObj is a resource object    
      30.         using (Car carObj = new Car())    
      31.         {    
      32.              Console.WriteLine(carObjWithUsing.Name);    
      33.         }    
      34.     }    
      35. }     
      36.         
      37. // If you run this program then you will get a error    
      38. // Error Number: CS1674.    
      39. // Error Description: 'Car': type used in a using statement must be implicitly convertible to 'System.IDisposable' or implement a suitable 'Dispose' method.    
    • Why is this error showing?

      • For using statement, the resource object must be implemeted with IDisposable interface, which is from System namespace.
      • If you go to IDisposable interface you can see that here is only one method, Dispose()
        1. namespace System    
        2. {    
        3.     //    
        4.     // Summary:    
        5.     //     Provides a mechanism for releasing unmanaged resources.    
        6.     public interface IDisposable    
        7.     {    
        8.         //    
        9.         // Summary:    
        10.         //     Performs application-defined tasks associated with freeing, releasing, or resetting    
        11.         //     unmanaged resources.    
        12.         void Dispose();    
        13.     }    
        14. }  
      • Here is full code with IDisposable
        1. // adding new code with highlighted       
        2. public class Car : IDisposable      
        3. {      
        4.     public string Name { getset; } = "Super Car";      
        5.       
        6.     public void Dispose()      
        7.     {      
        8.         Console.WriteLine("Disposing");      
        9.     }      
        10. }      
        11.           
        12.           
        13. class Program      
        14. {      
        15.    static void Main(string[] args)      
        16.    {      
        17.        //with using statement      
        18.        using (Car carObjWithUsing = new Car())      
        19.        {      
        20.             Console.WriteLine(carObjWithUsing.Name);      
        21.        }      
        22.    }      
        23. }      
        24.       
        25.       
        26. //Output       
        27. Super Car      
        28. Disposing   
         
    • This Dispose method is working well now. But I have written only one: 'Console.WriteLine("Disposing");' We must write informative code to dispose.
      1. // adding new code with highlighted       
      2. public class Car : IDisposable      
      3. {      
      4.     public string Name { getset; } = "Super Car";      
      5.       
      6.     public void Dispose()      
      7.     {      
      8.         Console.WriteLine("Disposing");      
      9.         this.Name = null;      
      10.     }      
      11. }      
      12.           
      13. class Program      
      14. {      
      15.     static void Main(string[] args)      
      16.     {      
      17.         Car carObjWithUsing = new Car();      
      18.         using (carObjWithUsing)      
      19.         {      
      20.             Console.WriteLine(carObjWithUsing.Name);      
      21.         }      
      22.         // Name will be null here.      
      23.         Console.WriteLine(carObjWithUsing.Name);      
      24.     }      
      25. }      
      26.           
      27. //Output       
      28. Super Car      
      29. Disposing      
    • Note
      If you assign null to an object, it is only removing reference of the object from the stack. Object is not removed from the heap.
    • The following code allows multiple instances of a type in a single statement:
      1. using (Car carObjWithUsing1 = new Car(), carObjWithUsing2 = new Car())    
      2. {    
      3.         
      4. }    
    • Note
      If you use more than one type within a single statement, then an exception will occur. For example:
      1. using (Car carObj = new Car(), Animal animalObj = new Animal())    
      2. {    
      3.                      
      4. }    
      5.     
      6. // Here have two types, Car and Animal.So we will get a error;     
      7. // Error Number: CS1044     
      8. // Error Details: Cannot use more than one type in a for, using, fixed, or declaration statement        
    • You can use a nested using statement.
      1. using (Customer customer = new Customer())    
      2. {    
      3.     using (Order order = customer.Order)    
      4.     {    
      5.         Console.WriteLine(order.ItemName);    
      6.     }    
      7. }     
      8.     
      9. // or you can use flowing syntax (but it's not working for old c# version):    
      10. using (Customer customer = new Customer())    
      11. using (Order order = customer.Order)     
      12. {     
      13.     Console.WriteLine(order.ItemName);    
      14. }   
  • How does it work?

    • Defines a boundary/Scope for the object. At the end of this boundary, it's called Dispose method automatically, which is written in resource class to dipose/release resource.

  • When do we use it?

    • For resource-intensive operations, object lifetime is important to dispose.
    • Use using statement in database connection because if any error occurs, then the database connection will be closed automatically. There's no need to call connection Close() method explicity.

  • Benefits:

    • Reduces the code
      • Example:
        1. using (Car carObj = new Car())    
        2. {    
        3.     Console.WriteLine(carObjWithUsing.Name);    
        4. }     
        5.     
        6. // you will get same result by try-catch-finally statement.    
        7.     
        8. Car carObj = new Car();    
        9. try    
        10. {    
        11.     Console.WriteLine(carObj.Name);    
        12. }    
        13. catch(Exception ex)    
        14. {    
        15.     
        16. }    
        17. finally    
        18. {    
        19.     if(carObj != null)    
        20.        ((IDisposable)carObj).Dispose();    
        21. }     
        22.     
        23. // From the above code, it's clear that using statement is reducing code.    
    •  Simpler Syntax
      • Example : see above in the code reduction example.
    • Saves development time and effort.
    • It ensures that Dispose is called even if an exception occurs within the using block.
      1. string connString = "Data Source=localhost;Integrated Security=True;Initial Catalog=Northwind;";      
      2.        
      3. using (SqlConnection conn = new SqlConnection(connString))      
      4. {      
      5.       SqlCommand cmd = conn.CreateCommand();      
      6.       cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";      
      7.       conn.Open();      
      8.        
      9.      ....    
      10.      ....     
      11. }     
      12.     
      13. // Here we dont need to write conn.Close(). It will call automatically.   
  • Disadvantages:
    Within the using block, the object is read-only and cannot be reassigned or modified.

Last Word

 
I would appreciate any suggestions to help improve my articles.