Заголовок этого сообщения обескураживает, не правда ли? Тем не менее, вы достаточно сообразительны, чтобы догадаться, о чем пойдет речь. На собеседовании по .NET часто задают вопрос: ”Чем отличаются директива using и оператор using?” Иногда перед соискателем ставят дополнительные ловушки, спрашивая, в каких местах программы можно использовать using? Первое, что приходит в голову, это использование директивы using, которая применяется для определения или разрешения использования типов как пространств имен. Например, следующий фрагмент кода демонстрирует включение некоторых пространств имен с помощью директивы using.

using System.IO;
using System.Text;

Погодите! Это не всё! Есть нечто, называемое “директивой псевдонимов (aliasing directive)” и ее можно использовать, как показано в следующей строке кода. Это может быть промежуточной частью ответа на вопрос.

using mynamespace = myproject.module;

Теперь вернемся к оператору using, который задает область видимости, вне которой объект недоступен. Рассмотрим следующий пример:

using(ColorImageFrame imageFrame = e.OpenColorImageFrame())
{
// здесь ваш код 
}

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

Комментарии (41)


  1. lair
    01.02.2016 15:30
    +5

    Ладно бы вы просто написали тривиальную информацию, так вы же еще и ошиблись.

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

    Нет такой вещи как «уничтожение объекта» в .net. Инструкция using всего лишь гарантирует (кстати, не на 100%) вызов Dispose (и одновременно ограничивает область видимости). Проще говоря, это синтаксический сахар вокруг try...finally.

    А для того, чтобы задать область видимости, using вообще не нужен, достаточно блок объявить.


    1. Sing
      01.02.2016 15:57

      > Проще говоря, это синтаксический сахар вокруг try...finally.

      Не совсем. Он ещё делает объект доступным только для чтения.

      > кстати, не на 100%

      А когда не гарантирует? Или вы о случае, когда объект инициируется в null?


      1. DrReiz
        01.02.2016 16:00
        +1

        Что означает фраза «делает объект доступным только для чтения»?


        1. Sing
          01.02.2016 16:02

          > Within the using block, the object is read-only and cannot be modified or reassigned.

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


          1. DrReiz
            01.02.2016 16:05
            +3

            В документации опечатка. Вместо слова 'object' подразумевается слово 'variable'.
            Соответственно: переменная, объявленная в using, не может быть переприсвоена. На сам объект никаких ограничений не накладывается.


            1. Sing
              01.02.2016 16:09
              -4

              В чём опечатка? В .NET все переменные — это объекты.


              1. lair
                01.02.2016 16:13
                +6

                Семантически, ошибка в том, что объект, на который ссылается переменная, может быть как угодно изменен (поэтому объект не read-only), однако никакая другая ссылка переменной быть присвоена не может (поэтому переменная — read-only).


              1. DrReiz
                01.02.2016 16:16
                +1

                Переменная и объект — это две разные сущности. Несколько переменных могут ссылаться на один объект, одна переменная может ссылаться на разные объекты (в разные моменты времени).

                Переменная — это ссылка на объект, размещается в стеке.
                Объект — это область памяти, хранящая данные объекта. Размещается в хипе.

                ps
                За скобкам оставлен вариант с value-типами.


                1. DrReiz
                  01.02.2016 16:22
                  +2

                  Изменение переменной не меняет объект. Изменение объекта не меняет переменную.


                1. Sing
                  01.02.2016 16:39
                  +2

                  Да, точно, моя ошибка.

                  Структуры в using изменять не получится, т.е. в этом случае и объект тоже read-only.


      1. lair
        01.02.2016 16:07

        Не совсем. Он ещё делает объект доступным только для чтения.

        Это следствие того же синтаксического сахара.

        А когда не гарантирует?

        Если по каким-то причинам случилось исключение после присвоения, но до входа в try (например, ThreadAbort). Или, что более занятно, если вы используете using вместе с object initializer (кстати, мне интересно, не поменяли ли это поведение после C# 4).


        1. a553
          01.02.2016 16:08

          Не поменяли.


        1. aikixd
          01.02.2016 19:36

          Какой тогда смысл использовать using, а не try?


          1. lair
            01.02.2016 20:29

            Во-первых, using лучше показывает ваше намерение.
            Во-вторых, у вас меньше шансов допустить какую-нибудь глупую ошибку в реализации.

            (ну и в-третьих, это занимает ощутимо меньше кода)


      1. imanushin
        02.02.2016 10:41
        +2

        А когда не гарантирует? Или вы о случае, когда объект инициируется в null?


        Один простой способ, но очевидный:

        using(new CompositeDisposable(databases.Select(db=>db.OpenTransaction()))
        {
            /**/
        }
        


        CompositeDisposable

        Если упадет ошибка при создании второй транзакции, то объект под using'ом не будет создан. С try-finally произойдет ровно то же самое, магии тут нет.

        Есть еще простой способ не вызвать Dispose — см. ниже разницу в наличии await. Класс Task реализует IDisposable, кстати )

        using(await db.OpenTransactionAsync())
        {
            /**/
        }
        
        using(db.OpenTransactionAsync()) //тут мы прибьем только таску, так что для синхронных операций ошибку заметим не сразу.
        {
            /**/
        }
        


  1. IL_Agent
    01.02.2016 16:22
    +18

    Заголовок этого сообщения обескураживает, не правда ли?

    Да и содержимое «сообщения» тоже слегка :)