Поговорите об этом с коллегой по работе. У нас есть некоторые мысли по этому поводу, но нам интересно, что думает по этому поводу SO толпа?
Поговорите об этом с коллегой по работе. У нас есть некоторые мысли по этому поводу, но нам интересно, что думает по этому поводу SO толпа?
Ответы:
Одна из причин - отсутствие поддержки CLR для локального файла только для чтения. Только чтение транслируется в код операции CLR / CLI только для инициализации. Этот флаг может применяться только к полям и не имеет значения для локального. Фактически, применение его к локальному, скорее всего, приведет к созданию непроверяемого кода.
Это не значит, что C # не может этого сделать. Но это даст два разных значения одной и той же языковой конструкции. Версия для местных жителей не будет иметь сопоставления, эквивалентного CLR.
readonly
Ключевое слово для полей должно поддерживаться CLI , поскольку его эффект является видимым для других узлов. Все это будет означать, что переменная имеет только одно назначение в методе во время компиляции.
const
(который в C ++ больше похож на C #, readonly
чем на C # const
, хотя он может играть обе роли). Тем не менее, C ++ поддерживает const
локальные автоматические переменные. Следовательно, отсутствие поддержки CLR для C # readonly
для локальной переменной не имеет значения.
using
и out
делают именно это, и мир не рухнул.
Я думаю, что это плохое суждение со стороны архитекторов C #. Модификатор readonly для локальных переменных помогает поддерживать корректность программы (как и утверждения) и потенциально может помочь компилятору оптимизировать код (по крайней мере, в случае других языков). Тот факт, что он сейчас запрещен в C #, является еще одним аргументом в пользу того, что некоторые из «функций» C # являются просто применением личного стиля кодирования его создателей.
Обращаясь к ответу Джареда, это, вероятно, должно быть просто функцией времени компиляции - компилятор запретит вам писать в переменную после первоначального объявления (которое должно включать присваивание).
Могу ли я увидеть в этом ценность? Потенциально - но, если честно, не очень. Если вы не можете легко определить, будет ли переменная назначена где-либо еще в методе, значит, ваш метод слишком длинный.
Для чего это стоит, Java имеет эту функцию (используя final
модификатор) , и я очень редко видел его использовали другие , чем в тех случаях , когда оно имеет быть использовано , чтобы позволить переменной быть захваченными анонимного внутреннего класса - и где он находится при использовании он создает впечатление беспорядка, а не полезной информации.
readonly
/ final
значение из переменных с его val
и var
ключевыми словами. В коде Scala локальные val
s используются очень часто (и фактически предпочтительнее локальных var
). Я подозреваю, что основными причинами того, что final
модификатор не используется более часто в Java, являются а) беспорядок и б) лень.
readonly
это не будет слишком важно. С другой стороны, для локальных переменных, которые используются в замыканиях, readonly
во многих случаях компилятор может генерировать более эффективный код. В настоящее время, когда выполнение входит в блок, содержащий замыкание, компилятор должен создать новый объект кучи для закрытых переменных, даже если код, который использовал бы замыкание, никогда не выполняется . Если бы переменная была доступна только для чтения, код вне замыкания мог бы использовать обычную переменную; только когда создается делегат для закрытия ...
Команда разработчиков C # 7 вкратце обсудила предложение только для чтения locals и параметров для. Из заметок о совещании разработчиков C # от 21 января 2015 г . :
Параметры и локальные переменные могут быть захвачены лямбдами и, таким образом, доступны одновременно, но нет способа защитить их от проблем с общим взаимным состоянием: они не могут быть доступны только для чтения.
В общем, большинство параметров и многие локальные переменные никогда не предназначены для присвоения после того, как они получат свое начальное значение. Разрешение только для чтения на них ясно выразит это намерение.
Одна из проблем заключается в том, что эта функция может быть «привлекательной помехой». В то время как «правильным» почти всегда было бы сделать параметры и локальные переменные только для чтения, это значительно загромождает код.
Идея, чтобы частично облегчить это, состоит в том, чтобы разрешить комбинацию только для чтения var в локальной переменной быть сокращенной до val или чего-то подобного. В более общем плане мы могли бы попытаться просто придумать более короткое ключевое слово, чем установленное слово «только для чтения», чтобы выразить эту возможность.
Обсуждение продолжается в репозитории C # Language Design. Проголосуйте, чтобы показать свою поддержку. https://github.com/dotnet/csharplang/issues/188
Я был тем коллегой, и это было неприятно! (просто шучу)
Я бы не стал исключать эту возможность, потому что лучше писать короткие методы. Это немного похоже на то, что вы не должны использовать потоки, потому что они сложны. Дайте мне нож и позвольте мне не порезаться.
Лично мне нужно другое ключевое слово типа «var», например «inv» (invarient) или «rvar», чтобы избежать беспорядка. В последнее время я изучаю F # и нахожу неизменное привлекательным.
Никогда не знал, что у Java есть это.
Мне нужны локальные переменные только для чтения так же, как мне нравятся локальные константные переменные. Но он менее приоритетен, чем другие темы.
Возможно, его приоритет является той же причиной, по которой дизайнеры C # (пока!) Не реализовали эту функцию. Но в будущих версиях должно быть легко (и иметь обратную совместимость) поддержка локальных переменных только для чтения.
Только чтение означает, что единственное место, где может быть установлена переменная экземпляра, - это конструктор. При локальном объявлении переменной у нее нет экземпляра (он находится только в области видимости), и конструктор не может его коснуться.
Я знаю, это не ответ на ваш вопрос. В любом случае, читатели этого вопроса, тем не менее, могут оценить приведенный ниже код.
Если вы действительно заинтересованы в том, чтобы выстрелить себе в ногу при переопределении локальной переменной, которая должна быть установлена только один раз, и вы не хотите делать ее более доступной глобально, вы можете сделать что-то вроде этого.
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
но он работает.
Вы можете объявить локальные переменные только для чтения в C #, если вы используете интерактивный компилятор C # 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)
Вы также можете объявить локальные переменные только для чтения в .csx
формате скрипта.
message
это не переменная, она скомпилирована в поле. Это не придирки, потому что различие явно существует и в интерактивном C #: int x; Console.WriteLine(x)
разрешен интерактивный C # (потому что x
это поле и неявно инициализировано), но void foo() { int x; Console.WriteLine(x); }
нет (потому что x
это переменная и используется до ее назначения). Кроме того, Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType
будет показано, что x
это действительно поле, а не локальная переменная.
С # уже имеет переменную только для чтения, хотя и с несколько другим синтаксисом:
Рассмотрим следующие строки:
var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;
Сравнить с:
var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();
По общему признанию, первым решением могло бы быть меньше кода для написания. Но второй фрагмент делает явным только чтение при ссылке на переменную.
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");
.
используйте 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);
}
}
const
котором переменная может быть назначена только во время ее инициализации, а не стиль csharp, в const
котором могут использоваться только выражения времени компиляции. Например, вы не можете этого сделать, const object c = new object();
но readonly
местный житель позволит вам это сделать.