Когда следует использовать "использование" блоков в С#?

Существуют ли особые случаи, когда я должен (или не должен?) использовать "использование" блоков:

using(SomeType t = new SomeType()){
    ...
}

Ответ 1

Когда класс SomeType реализует IDisposable.

Ответ 2

Некоторые объекты нуждаются в некоторых действиях, которые необходимо предпринять, когда вы закончите с ними. Обычно это происходит потому, что объект использует какой-то ресурс, который нужно утилизировать. Например, если у вас есть файловый объект класса File, и этот объект открывает файл из файловой системы, файл в файловой системе должен быть снова закрыт.

Если вы только что покинули объект файла и забыли вызвать файл .Close(), он не будет очищен до тех пор, пока не будет запущен сборщик Garbage Collector (GC) и ничего не будет работать с файловым объектом. Когда запускается сборщик мусора, он должен быть оставлен на время выполнения Common Language Runtime (CLR). Если GC не запускается довольно долго после того, как вы закончили с файлом, файл может оставаться открытым потенциально в течение длительного времени. Это может представлять большую проблему, если есть много файловых объектов или если что-то хочет открыть файл, но не может, потому что оставшийся объект файла все еще висит вокруг.

Чтобы решить эту проблему, С# имеет интерфейс IDisposable. У этого метода есть метод Dispose. Классы, требующие некоторой очистки, реализуют этот метод Dispose. Это дает вам стандартный способ очистки любых объектов, использующих ресурсы. Существует много классов, которым необходимо вызвать Dispose. Проблема заключается в том, что код распространяется на вызовы Dispose, и им сложно следовать, потому что место, где вы новичок в объекте, и вызываете Dispose для его очистки, различны. Таким образом, вам пришлось много оглядеть код и быть очень осторожным, чтобы проверить, были ли вызовы Dispose в нужном месте.

Чтобы решить эту проблему, С# представила ключевое слово 'using'. Вы можете поместить ключевое слово 'using', где вы новый объект, и это гарантирует, что Dispose будет вызван на него для вас. Это гарантирует, что Dispose будет вызываться независимо от того, что произойдет... даже если есть исключение, выведенное внутри тела оператора using.

Итак, вы должны использовать "использование", когда хотите убедиться, что объект, который выделяет ресурсы, будет очищен.


использование может использоваться только для объектов, объявленных в стеке, то есть в функции. Он не работает для объектов, объявленных как члены класса. Для них вы должны вызвать Dispose самостоятельно. Возможно, вам придется реализовать Dispose в своем классе, чтобы он мог вызывать Dispose на любых объектах-членах, которые ему требуются.


Обычными объектами, которые нужно использовать вызываемые на них, являются: Файлы, подключения к базе данных, объекты графики, такие как ручка и кисть.


Иногда он также используется, когда вы хотите, чтобы две операции выполнялись вместе. Например, если вы хотите написать оператор журнала, когда вводится блок кода, и когда он выйдет, вы можете написать класс журнала, который вы можете использовать следующим образом:

using( Log log = new Log("Doing stuff") )
{
    // Stuff
}

Конструктор для класса журнала может быть создан для записи сообщения, а метод Dispose также может записать его. Внесите финализатор (~ Log), чтобы подтвердить, если метод Dispose не вызван, чтобы обеспечить "использование" в "новом журнале".

Ответ 3

Используйте using всякий раз, когда тип реализует IDisposable, если вы не поместите его в блок try/catch, тогда вы также можете (в зависимости от какой вы предпочитаете) используйте блок finally.

Ответ 4

Я вижу много других ответов, которые указываются, когда вы должны иметь инструкцию using. Я хочу обратиться, когда конкретно не должен иметь оператор using:

Если вам нужно использовать свой объект за пределами области действия текущей функции, не нужно иметь блок using. Хорошим примером является метод factory, который возвращает соединение с базой данных или метод, который должен возвращать datareader. В любом из этих случаев, если вы создадите свой объект с помощью оператора using, он будет удален до возврата метода и, следовательно, не будет использоваться вне метода.

Теперь вы все же хотите быть уверенным в том, что эти объекты расположены, поэтому вам все равно может понадобиться инструкция using. Просто не включайте его в метод, где объект фактически создан. Вместо этого вы можете обернуть вызов функции в выражении using.

Ответ 5

Когда SomeType реализует IDisposable.

Это подсказывает разработчику, что SomeType использует неуправляемые ресурсы, которые необходимо очистить.

Ответ 6

Пример:

        using(SqlConnection MyConnection = new SqlConnection("Connection string"))
        {
            MyConnection.Open();

            //...

            // 1. SQLConnection is a type that implements IDisposable
            // 2. So you can use MyConnection in a using statement
            // 3. When using block finishes, it calls Dispose method of 
            // SqlConnection class
            // 4. In this case, it will probably close the connection to 
            // the database and dispose MyConnection object

        }

Вы можете создать свои собственные объекты, которые реализуют IDisposable:

public class MyOwnObjectThatImplementsIDisposable : IDisposable
{

    //... some code

    public void Dispose()
    {
        // Put here the code you want to be executed when the
        // using statement finish.
    }
}

Таким образом, вы можете использовать объект типа MyOwnObjectThanImplementsIDisposable в операторе using:

        using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable)
        {

            // When the statement finishes, it calls the 
            // code you´ve writed in Dispose method
            // of MyOwnObjectThatImplementsIDisposable class
        }

Надеюсь, что это поможет

Ответ 7

В этом контексте оператор using удобен для типов, реализующих IDisposable. Когда блок кода выходит из области действия оператора using, Dispose() называется неявным. Это хорошая привычка при работе с объектами, которые вы хотите утилизировать сразу после использования.

Ответ 8

Один конкретный экземпляр, в котором вы должны быть осторожны с использованием блока using, с клиентом службы WCF.

Как отмечено в этой статье MSDN, обертка WCF-клиента (который реализует IDisposable) в блоке using может маскировать любые ошибки, приводящие к тому, что клиент остается в неисправном состоянии (например, тайм-аут или проблема связи). Короче говоря, когда вызывается Dispose(), запускается клиент Close(), но бросает и ошибочно, потому что он в неисправном состоянии. Исходное исключение затем маскируется вторым исключением. Нехорошо.

Существуют различные обходные пути, в том числе один в самой статье MSDN. Другие можно найти на IServiceOriented и blog.davidbarret.net.

Я предпочитаю последний метод, сам.

Ответ 9

Если вы хотите правило сводки. В любое время, когда объект использует IDisposable, где у вас не будет catch, используйте его. Использование, по существу, этого шаблона:

try
{
  //instantiate and use object
}
finally
{
  //dispose object
}

Если вам не нужна уловка, использование может спасти вас при вводе текста, что хорошо.

Ответ 10

Возможно, стоит упомянуть, что основной причиной добавления "использования" lo С# languge является следующее: некоторые ресурсы могут быть недостаточными, чтобы не было смысла ждать, пока GC вызовет IDisposable. Например, соединения БД. Если вы используете try/catch/, наконец, вы не закончите с висящим соединением, но соединение будет оставаться висящим до тех пор, пока GC не запустится, и это может занять некоторое время (если вы не закрываете его явно). Если вы используете "использование" (извините за каламбур), вы сразу же освободите соединение, даже если забыли закрыть его и даже если какое-то исключение произошло внутри блока использования.

Другая причина, как и предыдущие сообщения, заключается в том, что программисты не всегда используют, наконец, для очистки. Если вы не используете окончательно в случае исключения, вы получите утечку ресурсов...

Ответ 11

Одна из ситуаций заключается в том, когда вы хотите что-то сделать в начале блока кода, а затем отменить его в конце блока безоговорочно (даже если есть бросок).

Ctor для одноразового класса, который вы создаете (и вызываете внутри использования), выполнит действие, а затем метод Dispose отменит это действие. Обычно я использую его.

Ответ 12

Основное правило:     * Используйте инструкцию USING, когда объекты реализуют интерфейс IDisposable.

Этот интерфейс предоставляет метод Dispose, который должен освобождать ресурсы объекта. Если этот метод не вызывается, то объект будет оставаться в памяти до тех пор, пока CLR хочет выполнить сборку мусора. Если программист использует инструкцию USING, то в конце объект будет удален, и все ресурсы будут бесплатными.

Очень важно, чтобы все ресурсы, которые больше не использовались, были бесплатными как можно скорее.

Для получения дополнительной информации о нем просто перейдите по этой ссылке: microsoft

Ответ 13

Другие люди уже упоминали о "IDisposable".

Но одно из предостережений при использовании выражения "using" заключается в том, любые исключения, брошенные в "использование", не будут пойманы даже мысль "SomeType" будет удаляться независимо.

Итак, в следующем фрагменте

using (SomeType t = new SomeType()){
    throw new Exception("thrown within using");
}

throw new Exception("thrown within using"); не следует игнорировать.

Ответ 14

Я бы также добавил, что используйте инструкцию using(), если что-то реализует IDispose, а также если это то, что вы хотите избавиться от трюков, к ресурсам NON-MANAGED, таким как соединения с базой данных и файловые дескрипторы.

Если это обычный объект с именем List<T>, где T - это объект Customer, который содержит имена и адреса, тогда вам не нужно. Сборщик мусора достаточно умен, чтобы управлять этим для вас. Но сборщик мусора НЕ вернет подключения к пулу подключений или закрывает дескрипторы файлов.