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

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

12 ответов


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

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


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


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

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

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


предложение readonly местные жители и параметры for был кратко обсужден проектной группой C# 7. От C# Design Meeting Notes для 21 января 2015:

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

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

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

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

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


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

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

лично я хотел еще "ВАР" тип сайта, как "инв" (invarient) или "rvar", чтобы избежать беспорядка. В последнее время я изучаю F# и нахожу неизменную вещь привлекательный.

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


Я хотел бы местные только для чтения переменные таким же образом, как мне нравится local 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 но это работает.


вы можете объявить только локальные переменные readonly в C#, если вы используете интерактивный компилятор C#csi:

>"C:\Program Files (x86)\MSBuild.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 формат сценария.


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


использовать 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);
    }
}