Why must I use Dispose()?

≡放荡痞女 提交于 2019-12-12 01:54:24

问题


Here is my code:

public void InsertData()
{
    using (SqlConnection connection = new SqlConnection(DBHelper.ConnectionString))
    {
        using (SqlCommand command = new SqlCommand("Some Simple Insert Query", connection))
        {
            connection.Open();
            command.ExecuteNonQuery();
        }
    }
}

But I found this code sample:

public void InsertData()
{
    SqlConnection connection = new SqlConnection(DBHelper.ConnectionString);
    connection.Open();
    SqlCommand command = new SqlCommand("Some Simple Insert Query", connection);
    command.ExecuteNonQuery();

    command.Dispose();
    connection.Close();
    connection.Dispose();
}

why does the author use

command.Dispose()

and

connection.Dispose();

in their code?


回答1:


using can only be used on objects that are disposable (which is when they implement the interface IDisposable). Doing so will automatically call Dispose on that instance. However in contrast to call it yourself the using-statement ensures that Dispose is also called when an exception whithin that block occurs. So it´s safer to use that approach.

Your first example is equivalent to this:

try 
{
    SqlConnection connection = new SqlConnection(DBHelper.ConnectionString);
    connection.Open();
    SqlCommand command = new SqlCommand("Some Simple Insert Query", connection);
    try 
    {            
        command.ExecuteNonQuery();
    } 
    finally 
    {
        command.Dispose();
    }
}
finally
{
    connection.Dispose();
}



回答2:


You'll have resource leak when exception has been thrown:

public void InsertData()
{
    SqlConnection connection = new SqlConnection(DBHelper.ConnectionString);
    connection.Open();
    SqlCommand command = new SqlCommand("Some Simple Insert Query", connection);
    command.ExecuteNonQuery(); // <- imagine that this throws exception 

    // and so these don't execute at all and you'll have two resources leaked: 
    //  1. Connection
    //  2. Command
    command.Dispose();
    connection.Close();
    connection.Dispose();
}

The reasons of the exception can vary:

1. Insert failed (e.g. invalid field value insertion)
2. User doesn't have privelege required
3. RDMBS Internal error 
...

You can emulate using with try .. finally which is wordy:

public void InsertData()
{
    SqlConnection connection = null;

    try {
      connection = new SqlConnection(DBHelper.ConnectionString);
      connection.Open();

      SqlCommand command = null;

      try {
         command = new SqlCommand("Some Simple Insert Query", connection);
         command.ExecuteNonQuery(); 
      }
      finally { // rain or shine, dispose the resource (if it has been created)
        if (command != null)
          command.Dispose(); 
      }
    }
    finally { // rain or shine, dispose the resource (if it has been created)
      if (connection != null)
        connection.Dispose();
    }



回答3:


You don't have to use dispose in your example, because the using block does that for you.

See here: using Statement (C# Reference)




回答4:


He is using connection.Dispose(); because the person is inexperienced and is writing bad code that is not safe. If a exception is thrown the connection will never be disposed of causing it to remain open till the GC collects the connection maybe minutes or hours later.




回答5:


The using block is just syntactic sugar for the try/finally Dispose() pattern. This is all explained in the documentation.

Note you can also reduce the indentation in your code:

using (SqlConnection connection = new SqlConnection(DBHelper.ConnectionString))
using (SqlCommand command = new SqlCommand("Some Simple Insert Query", connection))
{
    connection.Open();
    command.ExecuteNonQuery();
}



回答6:


In .Net IDisposable and the Dispose method are used to clean up unmanaged resources.

.Net keeps track of managed resources so it can clean them up automatically, but it needs to have some help when dealing with unmanaged resources.

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

https://msdn.microsoft.com/en-us/library/system.idisposable.dispose(v=vs.110).aspx

The using statement is a way to automatically call the Dispose method when you're done using it.

Provides a convenient syntax that ensures the correct use of IDisposable objects.

It'll even get called if an exception is called.

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

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

The code which isn't using the using statements is incorrect.

It'll work most of the time, but if an exception occurs the unmanaged resources in SqlConnection could be left uncleaned.

As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement.



来源:https://stackoverflow.com/questions/41102713/why-must-i-use-dispose

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!