Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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.

Ответ 12

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