Посмотрите, как константы работают в .NET Framework
Что такое const?
Когда переменная помечена как const
, ее значение не может измениться.
eg. const int BoilingTempCelcius = 100;
Константа должна быть определена во время компиляции, что означает, что только примитивные типы (bool
, int
, long
, string
etc) могут быть помечены как 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.
Резюме
Из-за того, как работают константы, и проблем с управлением версиями между сборками, которые могут возникнуть, важно использовать их только для значений, которые никогда не могут измениться.