tl; dr для локальных переменных с литеральными значениями, const
не имеет значения вообще.
Ваше различие между "внутренними методами" очень важно.Давайте посмотрим на это, затем сравним его с const
полями.
Const локальные переменные
Преимущество * *1013* локальной переменной 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
мы видим следующий (сокращенный) IL:
.method private hidebysig static string LocalVarString() cil managed
{
ldstr "hello"
ret
}
.method private hidebysig static string LocalConstString() cil managed
{
ldstr "hello"
ret
}
Как вы можете видеть, они оба производят одинаковый IL.Независимо от того, локальный s
равен const
или нет, это не влияет.
То же самое верно для примитивных типов.Вот пример использования int
:
private static int LocalVarInt()
{
var i = 1234;
return i;
}
private static int LocalConstInt()
{
const int i = 1234;
return i;
}
И снова IL:
.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
с переменным полем отличается от .Неконстантное поле должно читаться во время выполнения.Таким образом, вы получите IL следующим образом:
// Load a const field
ldc.i4 1234
// Load a non-const field
ldsfld int32 MyProject.MyClass::_myInt
Понятно, как это может привести к разнице в производительности, если предположить, что JIT не может встроить само постоянное значение.
Еще одно важное отличиездесь для открытых константных полей, которые являются общими для всех сборок.Если одна сборка предоставляет поле const, а другая использует его, то фактическое значение этого поля копируется во время компиляции .Это означает, что если сборка, содержащая поле const, обновлена, но используемая сборка не перекомпилирована, будет использовано старое (и, возможно, неправильное) значение.
Const выражений
Рассмотримэти два объявления:
const int i = 1 + 2;
int i = 1 + 2;
Для формы const
сложение должно быть вычислено во время компиляции, то есть число 3 сохраняется в IL.
Для не const
форма, компилятор может свободно генерировать операцию сложения в IL, хотя JIT почти наверняка применяет базовую оптимизацию константы, поэтому сгенерированный машинный код будет идентичен.
C # 7.3Компилятор выдает ldc.i4.3
код операции для обоих приведенных выше выражений.