Почему переменная, объявленная в операторе using, считается только для чтения? - PullRequest
4 голосов
/ 14 мая 2011

Почему using переменная считается только для чтения? Это спецификация языка c # или спецификация управляемых языков? Это потому, что c # - это язык .net? Заранее спасибо.

Примечание : переменная использования - это переменная, которая появляется в операторе использования

пример кода:

using (Form s = new Form)
{
    myfunc(ref s);
}

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

Примечание : я не хочу, чтобы вы обсуждали ключевое слово readonly.

Ответы [ 4 ]

11 голосов
/ 14 мая 2011

Я смотрю на (устаревшую?) Спецификацию [1] прямо сейчас.

15.13 говорит, что переменные, которые вы объявляете в части получения ресурса, доступны только для чтения.То есть:

var form = new Form1();
using (form) {
    form = null;
}

работает, а

using (var form = new Form1()) {
    form = null;
}

- нет.Это отвечает на часть вопроса (то есть, почему? Потому что это часть спецификации ...), но я понимаю, что это не совсем удовлетворительно.Но зачем вам это делать?


Редактировать: Подумав об этом, позвольте мне предложить возможное объяснение этого правила:

У вас есть

using (var something = new Foo()) {
   something = /* whatever */
}

и компилятор позволяет это.А что если Foo понадобится много неуправляемых ресурсов (возможно, именно поэтому вы и хотели использовать using в первую очередь)?После использования блока у вас больше нет доступа к этой ссылке.Он не был утилизирован, потому что вы переназначили something и забыли справиться с этим самостоятельно.У вас нет гарантии, что GC работает, вообще.Или когда.Вы только что создали утечку ресурсов, которая скрыта и скрыта.


Последняя, ​​вдохновленная ссылкой Хенка на блог Эрика Липперта, которая снова просто бросает нам спецификации:

оператор using в форме

оператор using (expression)

имеет те же два возможных расширения, но в этом случае ResourceType неявно является типом выражения времени компиляции,и переменная ресурса недоступна и невидима для встроенного оператора.

Другими словами:

var form = new Form1();
using (form) {
    form = null;
}

работает, потому что это расширено до

var form = new Form1();
var invisibleThing = form;
try {
   form = null;
} finally {
    if (invisibleThing != null) ((IDisposable)invisibleThing).Dispose();
}

Таким образом, в этом случае тот факт, что вы не имеете никакого влияния на ссылку using, скрыт от вас и точно такой же, как в предыдущем случае.

1: http://www.ecma -international.org/publications/standards/Ecma-334.htm

4 голосов
/ 14 мая 2011

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

2 голосов
/ 14 мая 2011

Прежде всего, в вашем примере, скорее всего, нет причины для модификатора ref.

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

Аннотированное руководство по C # 3 не дает объяснения.

Эрик Липперт затрагивает эту тему в посте о (не) боксе в заявлении об использовании .

Мой собственный удар по нему:

компилятор делает управляемую переменную только для чтения , поскольку она может .Если оставить эту переменную доступной для записи, откроется еще больше банок с червями, см. Статью о боксе Эрика.Обратите внимание, что аналогичное правило применяется к вложенной переменной в foreach().По сути, запись в эти переменные никогда не будет полезна, поэтому компилятор получает максимальный контроль над ними.

1 голос
/ 14 мая 2011

readonly - это ключевое слово в C #.Это полезно, когда вы хотите убедиться, что значение никогда не изменяется вне конструктора.

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

Редактировать : Мне любопытно, почему кто-то отверг мой ответ.Кто бы не проголосовал, пожалуйста, покажите мне, где мой ответ неверен?Спасибо.

...