Использование констант в статических классах - PullRequest
31 голосов
/ 13 апреля 2010

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

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

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). Атрибуты и модификаторы применяются ко всем члены объявлены постоянная декларация. Даже если константы считаются статическими члены, постоянная декларация не требует и не позволяет статический Модификатор. Это ошибка для того же модификатор, чтобы появиться несколько раз в объявление константы.

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

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

Ответы [ 4 ]

60 голосов
/ 14 апреля 2010

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога 10 июня 2010 года. Спасибо за отличный вопрос!

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

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

  1. Сделать статические необязательными : "const int x ..." или "static const int x ..." допустимы.

  2. Сделать статическим обязательным : «const int x ...» недопустимо, «static const int x ...» допустимо

  3. Сделать статические недопустимыми : «const int x ...» допустимо, «static const int x ...» недопустимо.

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

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

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

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

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

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

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

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

  1. сделать общедоступную статическую необязательной,

  2. сделать это требуется, или

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

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

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

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

  2. сделайте это обязательным: вы должны сказать новый или переопределить, или

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

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

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

43 голосов
/ 13 апреля 2010

Как правило, const подразумевает static уже, так как значение не может быть изменено во время выполнения. У вас нет причин объявлять static const , поскольку это уже подразумевается, и разработчики языка решили сделать так, чтобы синтаксис языка отражал это.

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

9 голосов
/ 13 апреля 2010

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

0 голосов
/ 18 апреля 2012

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

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

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

...