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

Использование констант в статических классах

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

Код в вопросах выглядит следующим образом:

internal static class SomeStaticClass
{
    private const int CommonlyUsedValue = 42;

    internal static string UseCommonlyUsedValue(...)
    {
        // some code
        value = CommonlyUsedValue + ...;

        return value.ToString();
    }
}

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

В спецификации указано (§10.4):

Объявление константы может включать набор атрибутов (§17), новый (§10.3.4) и действительным сочетание четырех модификаторов (§10.3.5). Атрибуты и модификаторы применяются ко всем членов, объявленных постоянная декларация. Хотя константы считаются статическими членов, декларация констант ни требует, ни статического модификатор.. Это ошибка для того же модификатор появится несколько раз в константная декларация.

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

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

4b9b3361

Ответ 1

В принципе, const подразумевает статический, поскольку значение не может быть изменено во время выполнения. Нет никаких оснований для того, чтобы вы когда-либо объявляли static const, поскольку это уже подразумевалось, и разработчики языка решили заставить синтаксис языка отражать это.

Язык спецификации в основном говорит: "Const всегда статична, поэтому вы не можете явно указывать static и const, поскольку она избыточна".

Ответ 2

UPDATE: Этот вопрос был предметом моего блога 10 июня 2010 года. Спасибо за отличный вопрос!

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

Предположим, что константы считаются статическими. Возможны три варианта:

  • Сделать static необязательным: "const int x..." или "static const int x..." являются законными.

  • Сделать статический обязательный: "const int x..." является незаконным, "static const int x..." является законным

  • Сделать static незаконным: "const int x..." является законным, "static const int x..." является незаконным.

Ваш вопрос: почему мы выбрали (3)?

Законопроекты с 1999 года не говорят; Я только что проверил. Но мы можем вывести, что, вероятно, происходит через руководителей дизайнер языка.

Проблема с (1) заключается в том, что вы можете читать код, который использует как "const int x...", так и "static const int y...", и тогда вы, естественно, спросите себя "какая разница?" Поскольку значение по умолчанию для непостоянных полей и методов является "экземпляром", если "статичным", естественным заключением было бы то, что некоторые константы являются экземплярами, а некоторые - для каждого типа, и этот вывод был бы неправильным. Это плохо, потому что это вводит в заблуждение.

Проблема с (2) заключается в том, что вначале она избыточна. Это просто больше набирает текст, не добавляя ясности или выразительности к языку. И, во-вторых, я не знаю о вас, но лично я ненавижу это, когда компилятор дает мне ошибку "Ты забыл сказать волшебное слово прямо здесь. Я знаю, что ты забыл сказать волшебное слово, я стопроцентный выяснить, что волшебное слово нужно туда идти, но я не собираюсь позволять вам выполнять какую-либо работу, пока вы не скажете волшебное слово".

Проблема с (3) заключается в том, что разработчику необходимо знать, что const логически подразумевает статичность. Однако, как только разработчик узнает об этом, они узнали об этом. Это не так, это сложная идея, которую трудно понять.

Решение, представляющее наименьшие проблемы и затраты для конечного пользователя, - это (3).

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

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

  • сделать public static необязательным,

  • сделайте это обязательным, или

  • сделать это незаконным.

Для перегруженных операторов мы выбрали (2). Поскольку естественное состояние метода является частным/экземпляром, кажется странным и вводящим в заблуждение сделать что-то похожее на метод public/static невидимо, как требуют (1) и (3).

В другом примере виртуальный метод с той же сигнатурой, что и виртуальный метод в базовом классе, должен иметь либо "новый", либо "переопределить" на нем. Опять же, три варианта.

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

  • сделайте это обязательным: вы должны сказать new или override, или

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

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

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

Ответ 3

Это не требуется или не допускается, потому что оно избыточно. Если все члены const статичны, то может возникнуть только путаница, позволяющая некоторым из них указываться как static, а некоторые из них не должны быть.

Ответ 4

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

Константы не имеют адреса памяти, и вы не можете получить ссылку на постоянное значение (единственным исключением являются строковые константы). Во время выполнения определение константы, содержащее константу, не будет загружаться, если другие статические/нестатические члены не будут ссылаться. Если это единственный тип в сборке, вы можете даже безопасно удалить DLL с диска после компиляции.

Таким образом, константы являются "статическими" только в терминах "могут ссылаться на статические методы". Константы не имеют никаких других "статических" свойств, как это делают другие члены статического типа.