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


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

12 86

12 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

это недосмотр для C# language designer. 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.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 формат сценария.

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

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