Как остановить С# от замены константной переменной их значениями?

У нас есть проект, скомпилированный в DLL, называемый consts.dll, который содержит что-то вроде:

public static class Consts
{
    public const string a = "a";
    public const string b = "b";
    public const string c = "c";
}

У нас есть несколько проектов такого рода, каждый из которых скомпилирован в DLL с таким же именем (consts.dll), и мы заменяем их в соответствии с потребностями. У нас есть еще один класс, который использует эти константы:

public class ConstsUser 
{
    string f() { return Consts.a; }
}

К сожалению, Consts.a оптимизирован для "a", поэтому, даже если мы заменим реализацию Consts.dll, мы по-прежнему получаем "a" вместо правильного значения, и нам нужно перекомпилировать ConstsUser. В любом случае, чтобы оптимизатор не заменил константные переменные своими значениями?

Ответ 1

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

public static class Consts
{
    public static readonly string a = "a";
    public static readonly string b = "b";
    public static readonly string c = "c";
}

Константы жестко закодированы на сайте вызова, так что это ваша проблема. Статическая переменная readonly может быть изменена только в объявлении переменной или статическом конструкторе класса Consts, и она не будет включена на сайт вызова.

Ответ 2

Из книги CLR через С#

Когда код ссылается на постоянный символ, компиляторы ищут символ в метаданные сборки, которая определяет константу, извлекают значение констант и встроить значение в испускаемое промежуточное звено Язык (IL). Поскольку значение константы встроено непосредственно в код, константы не требуют, чтобы для них была выделена память во время выполнения. Кроме того, вы не можете получить адрес константы, и вы не может передавать константу по ссылке. Эти ограничения также означают, что константы не имеют хорошей истории с версией перекрестной сборки, поэтому вы должны использовать их только тогда, когда вы знаете, что значение символа будет никогда не меняйте.

Как мы видим, использование const имеет свои преимущества, когда мы знаем, что значение символа никогда не изменится. Он может работать быстрее, потому что CLR не нуждается в разрешении.

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

Как уже было предложено @Sergey Berezovskiy, мы могли бы использовать static readonly, если вам нужно, чтобы CLR разрешала значение динамически во время выполнения. Это влияет на производительность, но есть и другое преимущество.

Кроме того, поле может иметь любой тип данных, поэтому вам не нужно ограничивайте свои компиляторы встроенными примитивными типами (так как вы do для констант).