Почему переменная, объявленная в операторе 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#. Это полезно, когда вы хотите убедиться, что значение никогда не изменяется вне конструктора.
Это ключевое слово может быть полезно, когда вы вносите код в большой проект, и вы беспокоитесь, что коллеги могут попытаться изменить переменную, которая никогда не должна изменяться.
Редактировать: мне любопытно, почему кто-то понизил мой ответ. Кто бы ни отрицал голос, пожалуйста, покажите мне, где мой ответ неверен? Благодарю.