Приветствую. Недавно я наткнулся на статью товарища Dywar «Интересные заметки по C# и CLR» и заинтересовался пунктом 13:
«Константы помещаются в метаданные сборки, поэтому если были изменения, нужно перекомпилировать все использующие ее сборки. Т.к. DLL с константой может даже не загружаться.»
Да ладно, подумал я, и полез ставить эксперименты. Создал проект TestConstants, в нем класс,
затем проект TestConstantsSlave,
Заменил константу на “Hello habr”, перебилдил основной проект, запустил по F5…
На консоли высветился “Hello habr”. Видимо, студия ребилднула заодно и Slave проект. В принципе, на этом можно было успокоиться, но хотелось немного поэкспериментировать.
Первым делом я заменил константу на “Greetings, sir von Neumann”, ребилднул основной проект, и запустил Slave через проводник → TestConstantsSlave.exe. На консоли светилось «Hello habr», да простит меня великий Нейман. Скопировал свежую библиотеку к Slave – по прежнему «Hello habr”. Удалил TestConstants библиотеку — снова “Hello habr”.Хабр молчал.
Неужели действительно константа копируется в метаданные? Открываем ildasm. В манифесте Slave все стандартно: версия, заголовки, токены. Константы нет (что разумно). Пробежал по классам — никаких метаданных в явном виде не обнаружено.
Зато в коде Slave есть «Hello habr» в явном виде.
Смотрим описание инструкции ldstr на msdn. “Pushes a new object reference to a string literal stored in the metadata“. Видимо, метаданные скрыты для ildasm. На всякий случай проверил dotPeek – результат аналогичен (зато видно, что Slave проект не ссылается на TestConstants).
Проверка константы другого типа: использование Int32 константы дает другой il код: ldc.i4.5. Здесь у нас простой пуш инта в стек (что опять-таки разумно — строки длинные, есть смысл их кэшировать, а вот накладные расходы на вытягивание инта из кэша перевешивают выхлоп). Видимо, в изначальной статье и msdn под метаданными подразумевается часть механизма интернирования строк (тунц, тынц), что, кстати, объясняет отсутствие метаданных в ildasm — пул строк генерируется для процесса.
Ничего страшного. Студия же правильно билдит, да и константы меняются не каждый день. С другой стороны, я уже работал с проектом, где SDK и использующие его утилиты находились в разных солюшнах, и обновление SDK могло породить «баг неизменной константы».
«Константы помещаются в метаданные сборки, поэтому если были изменения, нужно перекомпилировать все использующие ее сборки. Т.к. DLL с константой может даже не загружаться.»
Да ладно, подумал я, и полез ставить эксперименты. Создал проект TestConstants, в нем класс,
public class Master
{
public const string Const = "Hello world";
}
затем проект TestConstantsSlave,
static void Main()
{
Console.WriteLine(Master.Const);
Console.ReadKey();
}
Заменил константу на “Hello habr”, перебилдил основной проект, запустил по F5…
На консоли высветился “Hello habr”. Видимо, студия ребилднула заодно и Slave проект. В принципе, на этом можно было успокоиться, но хотелось немного поэкспериментировать.
Первым делом я заменил константу на “Greetings, sir von Neumann”, ребилднул основной проект, и запустил Slave через проводник → TestConstantsSlave.exe. На консоли светилось «Hello habr», да простит меня великий Нейман. Скопировал свежую библиотеку к Slave – по прежнему «Hello habr”. Удалил TestConstants библиотеку — снова “Hello habr”.
Неужели действительно константа копируется в метаданные? Открываем ildasm. В манифесте Slave все стандартно: версия, заголовки, токены. Константы нет (что разумно). Пробежал по классам — никаких метаданных в явном виде не обнаружено.
Зато в коде Slave есть «Hello habr» в явном виде.
Смотрим описание инструкции ldstr на msdn. “Pushes a new object reference to a string literal stored in the metadata“. Видимо, метаданные скрыты для ildasm. На всякий случай проверил dotPeek – результат аналогичен (зато видно, что Slave проект не ссылается на TestConstants).
Проверка константы другого типа: использование Int32 константы дает другой il код: ldc.i4.5. Здесь у нас простой пуш инта в стек (что опять-таки разумно — строки длинные, есть смысл их кэшировать, а вот накладные расходы на вытягивание инта из кэша перевешивают выхлоп). Видимо, в изначальной статье и msdn под метаданными подразумевается часть механизма интернирования строк (тунц, тынц), что, кстати, объясняет отсутствие метаданных в ildasm — пул строк генерируется для процесса.
И что дальше?
Ничего страшного. Студия же правильно билдит, да и константы меняются не каждый день. С другой стороны, я уже работал с проектом, где SDK и использующие его утилиты находились в разных солюшнах, и обновление SDK могло породить «баг неизменной константы».
Only registered users can participate in poll. Log in, please.
Встречались ли вы с «багом неизменной константы»?
13.48% Да36
86.52% Нет231
267 users voted. 97 users abstained.
Only registered users can participate in poll. Log in, please.
Стоит ли расследовать детали работы nameof()?
79.58% Да191
20.42% Нет49
240 users voted. 111 users abstained.