Почему C# запрещает локальные переменные, доступные только для чтения?

StackOverflow https://stackoverflow.com/questions/443687

Вопрос

Дружеская дискуссия по этому поводу с коллегой.У нас есть некоторые мысли по этому поводу, но интересно, что думает по этому поводу толпа SO?

Это было полезно?

Решение

Одна из причин в том, что в CLR нет поддержки только для чтения. Readonly переводится в код операции инициализации CLR / CLI. Этот флаг может применяться только к полям и не имеет значения для локального. На самом деле, применение его к локальному образцу может привести к непроверяемому коду.

Это не значит, что C # не может этого сделать. Но это дало бы два разных значения одной и той же языковой конструкции. Версия для местных жителей не будет иметь эквивалента CLR.

Другие советы

Я думаю, что это плохое суждение со стороны архитекторов C #. модификатор readonly для локальных переменных помогает поддерживать корректность программы (точно так же, как утверждает) и потенциально может помочь компилятору оптимизировать код (по крайней мере, в случае других языков). Тот факт, что это запрещено в C # прямо сейчас, является еще одним аргументом того, что некоторые из «функций» C # - это просто применение стиля персонального кодирования его создателей.

Обращаясь к ответу Джареда, это, вероятно, просто должна быть функция времени компиляции - компилятор запретит вам писать в переменную после первоначального объявления (которое должно включать в себя присваивание).

Могу ли я увидеть ценность в этом? Потенциально - но не много, если честно. Если вы не можете легко определить, будет ли переменная назначена в другом месте метода, значит, ваш метод слишком длинный.

Для чего бы то ни было, в Java есть эта функция (с использованием модификатора final ), и я очень редко видел, как она использовалась, за исключением случаев, когда она должен использоваться для того, чтобы переменная могла быть захвачена анонимным внутренним классом - и там, где она используется , создается впечатление беспорядка, а не полезной информации.

Предложение только для чтения локальные пользователи и параметры был кратко обсужден командой разработчиков C # 7. Из заметок о собрании разработчиков C # от 21 января 2015 года :

  

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

     

Как правило, большинство параметров и многие локальные объекты никогда не предназначены для назначения после получения их начального значения. Разрешение на чтение только для них ясно выразит это намерение.

     

Одной из проблем является то, что эта функция может быть "привлекательной неприятностью". Принимая во внимание, что «правильная вещь» почти всегда сделать так, чтобы параметры и локальные объекты были доступны только для чтения, для этого значительно помешал бы код.

     

Идея частично смягчить это состоит в том, чтобы разрешить сжатие комбинации readonly var для локальной переменной в val или что-то в этом роде. В более общем смысле мы могли бы попытаться просто придумать более короткое ключевое слово, чем установленное только для чтения, чтобы выразить готовность только для чтения.

Обсуждение продолжается в репозитории C # Language Design. Проголосуйте, чтобы показать свою поддержку. https://github.com/dotnet/csharplang/issues/188

Я был тем сотрудником, и он не был дружелюбным! (шучу)

Я бы не отказался от этой функции, потому что лучше писать короткие методы. Это все равно что сказать, что вы не должны использовать потоки, потому что они сложные. Дай мне нож и позволь мне не отвечать за себя.

Лично я хотел еще один "var" введите ключевое слово как " inv " (неизменный) или "rvar" чтобы избежать беспорядка. Я изучал F # в последнее время и считаю неизменную вещь привлекательной.

Никогда не знал, что у Java это есть.

Я хотел бы, чтобы локальные переменные только для чтения были такими же, как и локальные переменные const . Но это имеет меньший приоритет, чем другие темы.
Возможно, его приоритет является той же причиной, по которой дизайнеры C # не (пока!) реализуют эту функцию. Но в будущих версиях должно быть легко (и обратно совместимо) поддерживать локальные переменные только для чтения.

Это недосмотр со стороны дизайнера языка C#.В F# есть ключевое слово val, и оно основано на CLR.Нет никаких причин, по которым C# не может иметь такую ​​же языковую функцию.

Readonly означает, что единственное место, в котором можно установить переменную экземпляра, находится в конструкторе. При локальном объявлении переменной у нее нет экземпляра (она находится только в области видимости), и конструктор не может коснуться ее.

Я знаю, это не отвечает на вопрос «почему». В любом случае, тем, кто читает этот вопрос, может понравиться приведенный ниже код.

Если вы действительно заинтересованы в том, чтобы выстрелить себе в ногу при переопределении локальной переменной, которую следует устанавливать только один раз, и вы не хотите делать ее более общедоступной переменной, вы можете сделать что-то подобное.

    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 .

c # уже имеет переменную только для чтения, хотя и в несколько ином синтаксисе:

Рассмотрим следующие строки:

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();

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

Я думаю, это потому, что функция, имеющая переменную только для чтения, никогда не может быть вызвана, и, вероятно, что-то в ней выходит из области видимости, и когда вам это понадобится?

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

ссылка: https://docs.microsoft .com / EN-US / DotNet / CSharp / язык ссылок / ключевые слова / Const

public class SealedTest
{
    static void Main()
    {
        const int c = 707;
        Console.WriteLine("My local constant = {0}", c);
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top