Посмотрите, как константы работают в .NET Framework

Что такое const?

Когда переменная помечена как const, ее значение не может измениться.

eg. const int BoilingTempCelcius = 100;

Константа должна быть определена во время компиляции, что означает, что только примитивные типы (bool, int, long, stringetc) могут быть помечены как const.

Однако C # позволяет вам объявить непримитивный тип как const, если вы установите значение null:

eg. const SomeComplexType x = null;

Ссылка на константу из библиотеки

Давайте посмотрим на некоторые странные вещи, которые могут произойти с const при обращении к ним из библиотеки классов.

Проекты

Создайте новый проект консольного приложения .NET Framework под названием SomeConsoleApp и добавьте библиотеку классов в решение под названием SomeLibrary:

Класс Program.cs вашего консольного приложения должен иметь следующий код:

Создайте класс SomeClass в проекте SomeLibrary и вставьте этот код:

Запустите приложение

Постройте решение, затем запустите SomeConsoleApp.exe, который можно найти в <your project root folder>\SomeConsoleApp\SomeConsoleApp\bin\Debug.

Как и следовало ожидать, мы можем увидеть ценность 60.

Обновление и сборка

Теперь обновите значение с 60 до 70 в SomeClass.cs, сохраните файл и щелкните правой кнопкой мыши SomeLibrary в обозревателе решений, а затем выберите «Сборка».

Перезапустите приложение

Если вы снова запустите SomeConsoleApp.exe, вы заметите, что значение не изменилось:

Это кажется неинтуитивным, поскольку мы ссылались на SomeClass.SomeConst в нашем консольном приложении и перестроили проект, который изменился, то есть SomeLibrary.

Удалить ссылку

Посмотрим, что произойдет, если мы удалим ссылку на проект.

Перейдите в <your project root folder>\SomeConsoleApp\SomeConsoleApp\bin\Debug и удалите SomeLibrary.dll:

Перезапустите приложение

Если вы снова запустите SomeConsoleApp.exe, вы заметите, что значение все еще отображается!

Что тут происходит?

Во время компиляции значение SomeClass.SomeConst вставляется непосредственно в код CIL:

В строке 13 вы можете увидеть, что ссылка SomeClass.SomeConst была заменена фактическим значением 60.

Вот сгенерированный код C # на основе CIL:

Компилятор в основном находит в коде ссылку на const и заменяет его непосредственно значением.

Если вы хотите обновить значение до 70, вам необходимо перекомпилировать SomeConsoleApp.

Интересные факты

Это прямое вложение значения const приводит к некоторым интересным фактам:

  • Вы не можете поставить точку останова в строке с объявлением const (потому что эта строка фактически не существует во время выполнения).
  • Константам не требуется выделять для них память во время выполнения.
  • Вы не можете получить адрес константы.
  • Константу нельзя передать по ссылке.

Что насчет .NET 5.0?

Если вы настроите точно такое же решение / проекты с помощью .NET 5.0 и запустите SomeConsoleApp.exe, вы получите эту ошибку (чтобы увидеть ошибку, вам нужно открыть .exe через cmd):

Это связано с тем, что .NET 5.0 создает файл SomeConsoleApp.deps.json в папке \SomeLibrary\SomeConsoleApp\bin\Debug\net5.0:

Файл выглядит так:

Как видите, этот файл содержит ссылки на SomeLibrary.

Чтобы запустить SomeConsoleApp.exe, вам нужно удалить или переименовать SomeConsoleApp.deps.json.

Резюме

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

Ресурсы