2013-08-14 5 views
9

Интересно, почему мы используем оператор using на C#. Я просмотрел его и обнаружил, что он используется для выполнения операторов, а затем для очистки объектов. Поэтому мой вопрос: Разве это не то же самое, если мы открываем и закрываем фигурные скобки ({ }), чтобы определить область?Операция «using» против фигурных скобок

Используя оператор:

using (SqlConnection conn = new SqlConnection(connString)) { 
    SqlCommand cmd = conn.CreateCommand(); 
    cmd.CommandText = "SELECT * FROM Customers"; 
    conn.Open(); 
    using (SqlDataReader dr = cmd.ExecuteReader()) { 
      while (dr.Read()) 
      // Do Something... 
    } 
} 

Фигурные Скобки:

{ 
    SqlConnection conn = new SqlConnection(connString); 
    SqlCommand cmd = conn.CreateCommand(); 
    cmd.CommandText = "SELECT * FROM Customers"; 
    conn.Open(); 
    { 
      SqlDataReader dr = cmd.ExecuteReader(); 
      while (dr.Read()) 
      // Do Something... 
    } 
} 

Существуют ли какие-либо существенные различия между двумя методами?

+2

Что это связано с 'C++'? – BoBTFish

+0

Кудрявые скобки используются в C++ так, как они используются в этом вопросе, вот почему я запутался. Сожалею. –

ответ

4

Ну, с помощью (который является законным, если и только если класс реализует IDisposable интерфейс)

using (SqlConnection conn = new SqlConnection(connString)) { 
    // Some Code 
    ... 
} 

равно к этому блоку кода

SqlConnection conn = null; 

try { 
    SqlConnection conn = new SqlConnection(connString); 

    // Some Code 
    ... 
} 
finally { 
    if (!Object.ReferenceEquals(null, conn)) 
    conn.Dispose(); 
} 

C# не имеет то же поведение как C++ делает, поэтому не использовать {...} шаблон в C#, как вы это делаете в C++:

{ 
    SqlConnection conn = new SqlConnection(connString); 
    ... 
    // Here at {...} block exit system's behavior is quite different: 
    // 
    // C++: conn destructor will be called, 
    // resources (db connection) will be safely freed 
    // 
    // C#: nothing will have happened! 
    // Sometimes later on (if only!) GC (garbage collector) 
    // will collect conn istance and free resources (db connection). 
    // So, in case of C#, we have a resource leak 
} 
+0

Так что это буквально неважно, используем ли мы или пытаемся/наконец? Другой вопрос заключается в том, что, как я помню, мы также можем использовать catch между try и finally. Если мы хотим соответствовать этому блоку catch, какая часть используемого оператора охватывает это? –

+1

Да, вы совершенно правы: использование всего лишь синтаксического сахара. Если вы помещаете catch() в ту же самую попытку {...} с finally {}, она будет соответствовать try ... ... catch() {...} внутри using() {...}: используя (...) {попробуй поймать() {...} } –

0

с использованием эквивалентен следующих

SqlConnection conn; 
try 
{ 
    conn = new SqlConnection(connString) 
} 

finally 
{ 
    conn.Dispose() //using does this automatically for you 
} 

Правила есть когда некоторый класс реализует IDisposable вы можете использовать иСПользоВание блока вместо попытки поймать, наконец, образец

Если вы хотите больше понимания о том, как работает GC, прочитайте эту замечательную статью по Jeffery Richter

+0

Да, улов не будет. Это будет только попытка и, наконец, – Anand

+0

Действительно ли это заменяет 'Try/Catch'? Он только заменяет ** явный ** вызов 'Dispose'? – christiandev

+0

Как насчет блока catch? Я имею в виду, какая часть блока использования фактически соответствует блоку catch? –

2

фигурные в скобках просто указывается код блока

где в качестве Использование инструктирует GC для утилизации.

Любой класс, который реализует IDisposable, может использоваться с использованием.

использование по существу перевод (примечание нет catch). Если есть какое-то исключение, оно будет выброшено. но даже в этом случае соединение будет располагать

SqlConnection conn; 
try 
{ 
    conn = new SqlConnection(connString); 
} 
finally 
{ 
    if (conn != null) 
     conn.Dispose(); 
} 
0

имен изменяет имя поиска в то время как фигурные скобки создать новый стек, в котором могут быть созданы локальные переменные.

+0

Так что, используя не создавая новый стек для поиска локальных переменных? Это верно? –

+0

@Mert Toka: Я предполагал, что это касается C++. Я вижу, что теперь он снова помечен на C#. – user2672165

1

Если вы используете версию с ключом с помощью, то NET платформа работает метод Dispose освободить ресурсы, которые используются объектом. Таким образом, объект должен реализовать интерфейс IDisposable.Таким образом вы освобождаете ресурсы детерминированным способом (в отличие от Garbage Collector).

Настоятельно рекомендуется чистить НЕ управляемые ресурсы в методе Dispose , потому что GC не очищает его.

Кудрявые скобки определяют только область переменных, используемых внутри них, но не очищают ресурсы после того, как среда выполнения достигает закрывающей скобки. GC делает это недетерминированным способом в соответствии с его алгоритмами.

1

При использовании

using(...){ 
... code 
} 

это на самом деле использует шаблон, C# компилятор генерирует код для вызова метода Dispose реализуемого объекта, созданного в использовании блока.

Таким образом, для любого объекта, реализующего интерфейс IDisposable, вы можете использовать

using(var disposableObject = new DisposableObject()){ 
} 

когда компилирует compliler будет generage ниже код

DisposableObject disposableObject = null; 
try 
{ 
    disposableObject = new DisposableObject(); 
} 
finally{ 
    disposableObject.Dispose(); 
} 

Таким образом, используя (..) заявление обеспечить способ Утилизируйте одноразовые объект вызывается, даже если какое-либо исключение вызывается внутри оператора using.