tl; dr для локальних змінних з буквальними значеннями, const
взагалі не має різниці.
Ваше розмежування "внутрішніх методів" дуже важливо. Давайте подивимось на це, а потім порівняємо з const
полями.
Локальні змінні Const
Тільки перевагою const
локальної змінної є те , що значення не може бути перепризначений.
Однак const
обмежується примітивними типами ( int
, double
, ...) і string
, що обмежує його застосування.
Відступ: Є пропозиції для компілятора C # дозволити більш загальне поняття "лише для читання" місцевих жителів ( тут ), яке поширило б цю перевагу на інші сценарії. Вони , ймовірно , не розглядатиметься як const
ніби, і, ймовірно , мають інше ключове слово для таких декларацій (тобто let
або readonly var
або що - щось подібне).
Розглянемо ці два методи:
private static string LocalVarString()
{
var s = "hello";
return s;
}
private static string LocalConstString()
{
const string s = "hello";
return s;
}
Побудований в Release
режимі, ми бачимо наступний (скорочений) ІЛ:
.method private hidebysig static string LocalVarString() cil managed
{
ldstr "hello"
ret
}
.method private hidebysig static string LocalConstString() cil managed
{
ldstr "hello"
ret
}
Як бачите, вони обидва виробляють абсолютно однаковий ІЛ. Незалежно від місцевих s
IS const
чи ні , не має ніякого впливу.
Те саме стосується примітивних типів. Ось приклад використання int
:
private static int LocalVarInt()
{
var i = 1234;
return i;
}
private static int LocalConstInt()
{
const int i = 1234;
return i;
}
І знову Іллінойс:
.method private hidebysig static int32 LocalVarInt() cil managed
{
ldc.i4 1234
ret
}
.method private hidebysig static int32 LocalConstInt() cil managed
{
ldc.i4 1234
ret
}
Тож знову ми не бачимо різниці. Тут не може бути різниці в продуктивності чи пам’яті. Єдина відмінність полягає в тому, що розробник не може повторно призначити символ.
Поля const
Порівнюючи const
поле зі змінним полем є іншим. Поле, що не є const, має бути прочитане під час виконання. Отже, ви закінчуєте IL таким чином:
ldc.i4 1234
ldsfld int32 MyProject.MyClass::_myInt
Зрозуміло, як це може призвести до різниці в продуктивності, припускаючи, що JIT не може сам вбудувати постійне значення.
Інша важлива відмінність тут полягає у відкритих полях const, які розподіляються між зборами. Якщо одна збірка надає поле const, а інша використовує його, тоді фактичне значення цього поля копіюється під час компіляції . Це означає, що якщо збірка, що містить поле const, оновлена, але використовувана збірка не перекомпілюється, буде використано старе (і, можливо, неправильне) значення.
Const вирази
Розглянемо ці дві декларації:
const int i = 1 + 2;
int i = 1 + 2;
Для const
форми додавання має бути обчислене під час компіляції, тобто число 3 зберігається в ІЛ.
Що стосується неформальної const
форми, компілятор може вільно запускати операцію додавання в IL, хоча JIT майже напевно застосовував би базову постійну оптимізацію згортання, щоб сформований машинний код був ідентичним.
Компілятор С # 7.3 випромінює ldc.i4.3
опкод для обох наведених вище виразів.
const
. Це не дає компілятору жодної додаткової інформації. Перевірте цю відповідь, щоб дізнатися більше.