Pull to refresh

Comments 41

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

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

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

А для того, чтобы задать область видимости, using вообще не нужен, достаточно блок объявить.
> Проще говоря, это синтаксический сахар вокруг try...finally.

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

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

А когда не гарантирует? Или вы о случае, когда объект инициируется в null?
> Within the using block, the object is read-only and cannot be modified or reassigned.

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

В документации опечатка. Вместо слова 'object' подразумевается слово 'variable'.
Соответственно: переменная, объявленная в using, не может быть переприсвоена. На сам объект никаких ограничений не накладывается.
В чём опечатка? В .NET все переменные — это объекты.
Семантически, ошибка в том, что объект, на который ссылается переменная, может быть как угодно изменен (поэтому объект не read-only), однако никакая другая ссылка переменной быть присвоена не может (поэтому переменная — read-only).
Переменная и объект — это две разные сущности. Несколько переменных могут ссылаться на один объект, одна переменная может ссылаться на разные объекты (в разные моменты времени).

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

ps
За скобкам оставлен вариант с value-типами.
Изменение переменной не меняет объект. Изменение объекта не меняет переменную.
Да, точно, моя ошибка.

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

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

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

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

(ну и в-третьих, это занимает ощутимо меньше кода)
А когда не гарантирует? Или вы о случае, когда объект инициируется в null?


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

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


CompositeDisposable

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

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

using(await db.OpenTransactionAsync())
{
    /**/
}

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

Да и содержимое «сообщения» тоже слегка :)
UFO landed and left these words here
Попробую пояснить, зачем этот перевод был опубликован на Habre.
Не секрет, что при приеме на работу в качестве .NET-программиста соискатели обычно проходят собеседование, на котором им задают вопросы, позволяющие оценить глубину знаний. Вопросы, в том числе, и тривиальные.
Публикуются разные материалы, помогающие соискателям понять, на какие вопросы им возможно придется отвечать на собеседовании и примерный план ответа, а интервьюерам расширить круг таких вопросов.
Перевод одной из серии таких статей и был предложен читателям Habra в качестве пробного шара, чтобы оценить, насколько эта площадка подходит для публикации подобных материалов.
Развернувшаяся дискуссия позволила уточнить некоторые моменты использования оператора using. Спасибо всем!
Отдельно хочется поблагодарить читателя dymanoid за существенное дополнение, по нововведениям С# 6.0, касающихся применения using.
этот перевод

А что вам помешало указать оригинал материала?
В правилах Habra упоминается отдельная форма для публикации переводов с полями первоисточника. К своему стыду, при публикации материала в песочнице я ее не нашел, поэтому оставил все как есть, ограничившись указанием на перевод в тэгах.
Исправляюсь. Вот ссылка на первоисточник http://dailydotnettips.com/2013/09/06/using-or-using/
Если пройти по вашей ссылке, даже там в комментариях написано то же, что вам тут рассказали. Но вы это проигнорировали.
Проигнорировал. И что?
Если искать абсолютную истину в этом вопросе, то ближе всего к ней находится спецификация языка С#.
Проигнорировал. И что?

И то, что вы даете в своем посте ошибочную информацию. Если бы мне на собеседовании кто-то такое выдал, я бы его поправил (и счел, что он не знает, что на самом деле происходит).

спецификация языка С#

… которую вы тоже проигнорировали.
Если это замечание касается «уничтожения объекта», то, спасибо за поправку, я согласен с замечанием. В спецификации «удаление ресурса».
В спецификации «удаление ресурса».

Это где это? Точную цитату и ссылку привести можете?
Начать имеет смысл отсюда https://msdn.microsoft.com/ru-ru/library/ms228593.aspx
Там написано, как скачать английский вариант спецификации C# 5.0.
Русский вариант можно получить с VS 2015. Он находится в каталоге C:\Program Files\Microsoft Visual Studio 14.0\VC#\Specifications\1049.
Чтобы не затруднять вас, я приведу цитаты:
На английском:
8.13 The using statement
The using statement obtains one or more resources, executes a statement, and then disposes of the resource.
На русском:
8.13 Оператор using
Оператор using получает один или несколько ресурсов, выполняет заданный оператор языка и затем удаляет ресурсы.

Если есть какие-то претензии к переводу, то предложите собственный вариант.
Так вот, русский перевод — неверен. Никакого «удаления» ресурсов не происходит, происходит именно disposal, который и описан дальше. Что именно делает using — явно описано на страницах 258 и 259 английской спецификации от C# 5, начиная со слов «A using statement [...] corresponds to one of three possible expansions» (где, собственно, и видно, что нет никакого «удаления»).
Безусловно. Предложите корректный перевод предложения.
Я предлагаю такой:

Оператор using получает один или несколько ресурсов, выполняет заданный блок кода и затем вызывает метод Dispose().
Если «безусловно», то зачем же на это ссылаться?

А «корректного» перевода этого предложения не существует, есть только близкий по смыслу (например, Sing приводит такой). Именно поэтому работу инструкции using лучше всего сразу описывать в терминах ее подмены компилятором.
Ссылаться надо, во-первых, затем, что об этом просят. Во-вторых, это все-таки официальный документ, хотя и может содержать ошибки. В- третьих, чтобы эти ошибки можно было исправить.

Не понял, зачем слово «корректный» заключено в кавычки.

«Именно поэтому работу инструкции using лучше всего сразу описывать в терминах ее подмены компилятором.»
Где угодно, только не в спецификации. Русский перевод должен соответствовать исходному тексту.

Подозреваю, что корректный вариант все-таки существует. Рискну предложить следующий:

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

Описание механизма работы идет далее.

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

На данном уровне необходимо убедиться лишь в четкости базовых представлений соискателя. Т.е. выясняем что делает слово using, но не как. Уточнение деталей — по желанию интервьюера.
Где угодно, только не в спецификации. Русский перевод должен соответствовать исходному тексту.

А вы в курсе, что проблема универсального точного перевода не имеет решения?

Рискну предложить следующий:

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

Тоже неверно. Оператор (на самом деле — инструкция) ничего не освобождает (в управляемом C# вообще нет освобождения как такового), он именно вызывает метод. Ничего больше.

Кстати, хочу обратить внимание, что в исходной статье нет утверждения о том, что именно using удаляет или уничтожает объект.

Благодаря чему вообще непонятно, зачем нужен using.

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

Так вот, using делает ровно одно: гарантирует вызов Dispose. Как он это делает — действительно второй вопрос. Но ничего, кроме вызова Dispose, using не делает. Вот такие вот базовые представления, да.
Возможный корректный перевод:
«Оператор using получает один или несколько ресурсов, выполняет заданный оператор языка и затем дает распоряжение освободить ресурсы (вызывая метод Dispose)»
Пожалуй, пока это наиболее точное отражение действительности. Слегка смущает выражение в скобках, но поскольку следующий абзац спецификации, где объясняется, что такое ресурс, расставляет все по местам, небольшое забегание вперед не страшно.
Если это замечание касается «уничтожения объекта», то, спасибо за поправку, я согласен с замечанием. В спецификации «удаление ресурса».

Ну вот написали вы «объект imageFrame больше не потребуется, и он может быть удален». Вы же на собеседования ориентируетесь? Так вот, на собеседовании немедленно последует вопрос — чем описываемое вами поведение отличается от следующей конструкции:

{
ColorImageFrame imageFrame = e.OpenColorImageFrame();
// здесь ваш код 
}
Прекрасный вопрос для собеседования. Но задавать его или нет — на усмотрение интервьюера.
Вопрос в том, что на него отвечать кандидату, который прочитал ваш перевод и радостно думает, что теперь он все знает про using.
Надеюсь, что он не поленится прочитать и ваши комментарии.
Давайте теперь каждому дурацкому вопросу с собеседования будем посвящать статью на Хабре.
Я понимаю, если бы вопрос был интересным и было бы, что обсудить. Но это — просто глупость, по-моему.
Что интересно — вопрос чисто субъективный. Не знаю, как вам, а мне обсуждение не кажется совсем уж бесполезным.
Sign up to leave a comment.

Articles