Я сегодня провел какой-то рефакторинг и заметил странную вещь, которую не могу понять ... или, что лучше, частично согласен с тем, что нашел в сети, но у меня все еще есть вопросы.
Пожалуйста, рассмотрите этот простой пример
class Program
{
public static readonly string a = "a";
public const string b = "b";
static void Main(string[] args)
{
Console.WriteLine(a);
Console.WriteLine(b);
}
}
Теперь, если я посмотрю на сгенерированный IL-код (полученный через IL Browser от resharp)
Я вижу следующий код
.method private hidebysig static void
Main(
string[] args
) cil managed
{
.entrypoint
.maxstack 8
// [16 13 - 16 34]
IL_0000: ldsfld string ConsoleApp4.Program::a
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
// [18 13 - 18 34]
IL_000a: ldstr "b"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
// [19 9 - 19 10]
IL_0014: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0 // this
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
.method private hidebysig static specialname rtspecialname void
.cctor() cil managed
{
.maxstack 8
// [11 9 - 11 47]
IL_0000: ldstr "a"
IL_0005: stsfld string ConsoleApp4.Program::a
IL_000a: ret
} // end of method Program::.cctor
} // end of class ConsoleApp4.Program
Что касается статической строки, она ведет себя так, как я ожидал.Вместо этого для const он загружает новое значение в стек ... фактически смотрит на код операции ldstr здесь он говорит:
Добавляет новую ссылку на объект на строковый литерал, хранящийся вметаданные
Я прочитал здесь , что
Теперь, куда бы ни ссылался myInt в коде, вместо того, чтобы делать "ldloc".0 ", чтобы получить значение из переменной, MSIL просто загружает постоянное значение, которое жестко закодировано в MSIL.Таким образом, использование констант обычно дает небольшое преимущество в производительности и памяти. Однако для их использования необходимо иметь значение переменной во время компиляции и любые ссылки на эту константу во время компиляции, даже если они находятся вв другой сборке будет произведена замена.
Константы, безусловно, полезный инструмент, если вы знаете значение во время компиляции.Если вы этого не сделаете, но хотите убедиться, что ваша переменная установлена только один раз, вы можете использовать ключевое слово readonly в C # (которое сопоставляется с initonly в MSIL), чтобы указать, что значение переменной можно установить только в конструкторе;после этого будет ошибкой изменить его.Это часто используется, когда поле помогает определить идентичность класса, и часто устанавливается равным параметру конструктора.
Но почему я должен испытывать более высокую производительность?(даже если учесть, что это довольно подлый)?А как насчет памяти?
Заранее спасибо