В .NET, почему константы оцениваются во время компиляции, а не во время JIT? - PullRequest
13 голосов
/ 11 декабря 2010

Сегодня меня удивило, когда я изменил значение общедоступной константы в статическом классе, а затем заменил старую копию сборки на вновь скомпилированную версию. Сюрпризом было то, что существующая программа, которая ссылалась на сборку, не принимала новое значение константы. То есть я не перекомпилировал исполняемый файл, а просто заменил одну сборку.

Полное описание моего эксперимента на Насколько постоянна постоянная?

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

Ответы [ 2 ]

30 голосов
/ 11 декабря 2010

Константы должны быть константами . Для все время . Константами являются такие вещи, как значение пи или число протонов в атоме свинца.

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

Также см. Руководство по разработке инфраструктуры, в котором указано:

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

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

1 голос
/ 11 декабря 2010

Существует также третий способ объявления «констант»: открытое статическое свойство.

public static string ConstString {get{return "First test";}}

Это имеет семантику управления версиями поля только для чтения, но если джиттер встроен в геттер, он становится постоянной времени джита. И, в отличие от const, его можно использовать для пользовательских типов.

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

Я использовал это в своем типе FixedPoint, как это:

public struct FixedPoint
{
  private int raw;
  private const fracDigits=16;

  private FixedPoint(int raw)
  {
    this.raw=raw;
  }

  public static FixedPoint Zero{get{return new FixedPoint();}}
  public static FixedPoint One{get{return new FixedPoint(1<<fracDigits);}}
  public static FixedPoint MaxValue{get{return new FixedPoint(int.MaxValue);}}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...