Когда я должен использовать блоки “using” в C #?[дубликат]

StackOverflow https://stackoverflow.com/questions/567138

  •  05-09-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

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

using(SomeType t = new SomeType()){
    ...
}
Это было полезно?

Решение

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

Другие советы

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

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

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

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

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


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


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


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

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

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

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

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

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

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

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

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

Пример:

        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
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Я бы также добавил, что используйте using() утверждение, если что-то реализует IDispose а также, если то, от чего вы хотите избавиться, относится к НЕУПРАВЛЯЕМЫМ ресурсам, таким как подключения к базе данных и дескрипторы файлов.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top