Где сохранится значение свойства экземпляра класса в C# .NET?
Имеем такой класс:
class Foo {
public int Property => 123;
}
Как видим, свойство имеет только getter и всегда возвращает константное значение - литерал 123.
Если создать 2 и более экземпляров, продублируется ли значение 132, или Property будет указывать на одну область памяти?
Какой из вариантов окажется менее затратным Foo или Bar?
class Bar {
private static readonly int _ConstValue = 123;
public int Property => _ConstValue;
}
Ответы (1 шт):
Вопрос достаточно простой.
Начну с того, что если изменить второй пример вот так:
class Bar
{
private const int _ConstValue = 123;
public int Property => _ConstValue;
}
То оба класса будут оптимизированы на выходе в идентичный набор инструкций процессора.
Как известно, свойство - это группа методов get и set и в данном случае метод get_Property при использовании константы будет скомпилирован вот так.
mov eax, 0x7b
ret
Записать в регистр EAX константу 0x7b, что означает число 123 и вернуть из метода.
Весь вопрос сводится здесь к тому, чем будет отличаться static readonly поле и константа, и так как статическое поле инициализируется всего один раз за время выполнения приложения, то что там происходит при инициализации - с точки зрения производительности совершенно всё равно.
А вот как изменится сам метод get_Property - он просто начнет работать с памятью.
mov eax, [ecx+4]
ret
Записать в регистр EAX значение из ячейки памяти по адресу из регистра ECX со смещением 4 байта.
Код метода конечно будет изменяться в зависимости от условий вызова и доступных компилятору оптимизаций, но смысл останется тот же.
Как итог: что быстрее, записать ячейку памяти в регистр процессора или константу? Определенно константу, так как при этом процессору просто не нужно обращаться к памяти, значение константы уже у него будет в кеше в выполняемом коде.
Но стоит учесть, что обе инструкции работают молниеносно быстро, и разницу можно будет ощутить только с специфических случаях. Другими словами, про константы вместо статичных readonly полей не стоит забывать и по возможности использовать.
Если интересно, есть ли разница между литералом и константой - в скомпилированном коде её нет. Это совершенно одно и то же. Разница есть только на уровне C#.
