Почему переменная, объявленная в операторе using, считается только для чтения?

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

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

образец кода:

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

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

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

4 ответа

Решение

Я смотрю на (устаревшую?) Спецификацию [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 работает, вообще. Или когда. Вы только что создали утечку ресурсов, которая скрыта и скрыта.


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

Использование заявления формы

использование (выражение) заявление

имеет те же два возможных расширения, но в этом случае 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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам