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.
-
-
-
- using(resource, it can be a class object)
- {
-
- }
-
-
- using (<ClassName> <VariableName> = new <ClassName>())
- {
-
- }
-
-
-
-
-
- public class Car
- {
- public string Name { get; set; } = "Super Car";
- }
-
-
- class Program
- {
- static void Main(string[] args)
- {
-
- using (Car carObj = new Car())
- {
- Console.WriteLine(carObjWithUsing.Name);
- }
- }
- }
-
-
-
-
- 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()
- namespace System
- {
-
-
-
- public interface IDisposable
- {
-
-
-
-
- void Dispose();
- }
- }
- Here is full code with IDisposable
-
- public class Car : IDisposable
- {
- public string Name { get; set; } = "Super Car";
-
- public void Dispose()
- {
- Console.WriteLine("Disposing");
- }
- }
-
-
- class Program
- {
- static void Main(string[] args)
- {
-
- using (Car carObjWithUsing = new Car())
- {
- Console.WriteLine(carObjWithUsing.Name);
- }
- }
- }
-
-
-
- Super Car
- Disposing
- This Dispose method is working well now. But I have written only one: 'Console.WriteLine("Disposing");' We must write informative code to dispose.
-
- public class Car : IDisposable
- {
- public string Name { get; set; } = "Super Car";
-
- public void Dispose()
- {
- Console.WriteLine("Disposing");
- this.Name = null;
- }
- }
-
- class Program
- {
- static void Main(string[] args)
- {
- Car carObjWithUsing = new Car();
- using (carObjWithUsing)
- {
- Console.WriteLine(carObjWithUsing.Name);
- }
-
- Console.WriteLine(carObjWithUsing.Name);
- }
- }
-
-
- Super Car
- 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:
- using (Car carObjWithUsing1 = new Car(), carObjWithUsing2 = new Car())
- {
-
- }
- Note
If you use more than one type within a single statement, then an exception will occur. For example:
- using (Car carObj = new Car(), Animal animalObj = new Animal())
- {
-
- }
-
-
-
-
- You can use a nested using statement.
- using (Customer customer = new Customer())
- {
- using (Order order = customer.Order)
- {
- Console.WriteLine(order.ItemName);
- }
- }
-
-
- using (Customer customer = new Customer())
- using (Order order = customer.Order)
- {
- Console.WriteLine(order.ItemName);
- }
- 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:
- using (Car carObj = new Car())
- {
- Console.WriteLine(carObjWithUsing.Name);
- }
-
-
-
- Car carObj = new Car();
- try
- {
- Console.WriteLine(carObj.Name);
- }
- catch(Exception ex)
- {
-
- }
- finally
- {
- if(carObj != null)
- ((IDisposable)carObj).Dispose();
- }
-
-
- 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.
- string connString = "Data Source=localhost;Integrated Security=True;Initial Catalog=Northwind;";
-
- using (SqlConnection conn = new SqlConnection(connString))
- {
- SqlCommand cmd = conn.CreateCommand();
- cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
- conn.Open();
-
- ....
- ....
- }
-
-
- 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.