Проведя дружеские дебаты с коллегой по этому поводу. У нас есть некоторые мысли об этом, но интересно, что толпа SO думает об этом?
Почему С# запрещает чтение только локальных переменных?
Ответ 1
Одна из причин заключается в отсутствии поддержки CLR для локально только для чтения. Readonly преобразуется в операционный код CLR/CLI initonly. Этот флаг может применяться только к полям и не имеет значения для локального. Фактически, применение его к локальному, скорее всего, приведет к неконтролируемому коду.
Это не означает, что С# не может этого сделать. Но это дало бы два разных значения одной и той же языковой конструкции. Версия для локальных жителей не будет иметь эквивалентное отображение CLR.
Ответ 2
Я думаю, что это плохое мнение со стороны разработчиков С#. Модификатор readonly для локальных переменных помогает поддерживать правильность программы (точно так же, как утверждает) и может потенциально помочь компилятору оптимизировать код (по крайней мере, в случае других языков). Тот факт, что он запрещен на С# прямо сейчас, является еще одним аргументом в пользу того, что некоторые "функции" С# представляют собой просто принудительное использование стиля персонального кодирования его создателей.
Ответ 3
Адресация ответа Джареда, вероятно, просто должна быть функцией компиляции - компилятор запретил бы вам писать эту переменную после первоначального объявления (которое должно было бы включать назначение).
Можно ли увидеть значение в этом? Потенциально, но не очень, если честно. Если вы не можете легко определить, будет ли переменная назначаться в другом месте метода, ваш метод слишком длинный.
Для того, что стоит, Java имеет эту функцию (с помощью модификатора final
), и я очень редко видел, что он использовался иначе, чем в тех случаях, когда он должен использоваться, чтобы позволить переменной захватываться анонимным внутренним класс - и где он используется, он создает впечатление беспорядка, а не полезной информации.
Ответ 4
Я был тем коллегой, и это было не дружелюбно! (просто шучу)
Я бы не исключил эту функцию, потому что лучше писать короткие методы. Это немного похоже на то, что вы не должны использовать потоки, потому что они сложны. Дайте мне нож и позвольте мне нести ответственность за то, что я не разрезал себя.
Лично мне нужно другое ключевое слово типа "var", например "inv" (инвариантное) или "rvar", чтобы избежать беспорядка. Я изучал F # в последнее время и считаю непреложную вещь привлекательной.
Никогда не знал, что у Java это.
Ответ 5
Я бы хотел, чтобы локальные переменные readonly были такими же, как и локальные константные переменные. Но он имеет меньший приоритет, чем другие темы.
Возможно, его приоритет - та же самая причина, по которой разработчикам С# не удалось (пока!) Реализовать эту функцию. Но в будущих версиях должно быть легко (и обратно совместимо) поддерживать локальные переменные readonly.
Ответ 6
Readonly означает, что единственное место, где может быть установлено переменная экземпляра, находится в конструкторе. При объявлении переменной локально у нее нет экземпляра (он просто в области видимости) и не может быть затронут конструктором.
Ответ 7
Это надзор за разработчиком языка С#. F # имеет ключевое слово val и оно основано на CLR. Нет причин, по которым С# не может иметь одну и ту же языковую функцию.
Ответ 8
Я знаю, это не отвечает на вопрос, почему на ваш вопрос. В любом случае, те, кто читает этот вопрос, тем не менее могут оценить код ниже.
Если вы действительно заинтересованы в том, чтобы стрелять в себя, когда переопределяете локальную переменную, которую нужно установить только один раз, и вы не хотите превращать ее в глобально доступную переменную, вы можете сделать что-то вроде этого.
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
Пример использования:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
Может быть, не так меньше кода, как rvar rInt = 5
, но он работает.
Ответ 9
Предложение readonly locals and parameters for было кратко обсуждено командой разработчиков С# 7. Из Замечания по оформлению проекта С# для 21 января 2015 г.:
Параметры и локальные объекты могут быть захвачены lambdas и, таким образом, доступны одновременно, но нет способа защитить их от проблем с общим взаимным состоянием: они не могут быть прочитаны только.
В общем, большинство параметров и многие локальные жители никогда не должны назначаться после того, как они получают свое начальное значение. Разрешение на чтение только на них ясно выражало бы это намерение.
Одна из проблем заключается в том, что эта функция может быть "привлекательной неприятностью". Принимая во внимание, что "правильная вещь" всегда будет заключаться в том, чтобы сделать параметры и locals readonly, это значительно помешало бы этому коду.
Идея частично разрешить это заключается в том, чтобы разрешить комбинацию readonly var локальной переменной сжиматься до val или что-то вроде этого. В более общем плане мы могли бы попытаться просто подумать о более коротком ключевом слове, чем установленное readonly, чтобы выразить readonly-ness.
Обсуждение продолжается в репозитории С# Language Design. Проголосуйте, чтобы показать свою поддержку. https://github.com/dotnet/csharplang/issues/188
Ответ 10
Вы можете объявлять только локальные переменные readonly в С#, если вы используете интерактивный компилятор С# csi
:
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
Вы также можете объявить только локальные переменные readonly в формате .csx
script.
Ответ 11
используйте ключевое слово const
, чтобы сделать переменную только для чтения.
ссылка: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
Ответ 12
Я думаю, что потому, что функция, которая имеет переменную readonly, никогда не может быть вызвана, и, вероятно, что-то из нее выходит из области видимости и когда вам нужно?