There are many questions about this subject , but none (except one but still a short one) are dealing with the following scenario.
From C# 4 book:
Marc also wrote :
if you change the value of a const, you need to rebuild all the clients
Question :
1) Why is that? Are both static readonly
and const
— static
?
2) Where actually the values are saved ?
3) How does making a field static readonly
actually solve
this problem "behind the scene" ?
1)
const
is just resolved during compile time with the value that you have provided. Whilestatic readonly
is a static variable.2)
static
values are usually stored on a special area on the heap called High Frequency Heap. As I said previously consts are substituted at compile time.3) making it
static readonly
will solve the problem because you will be reading a variable value at runtime, not a value provided at compile time.no, a const is a const, not a static - it is a special-case, with different rules; it is only set at compile-time (not runtime), and it is handled differently
the crux here is what the following means:
vs
in the first case, it reads the value at runtime from
SomeType
, i.e. via aldsfld
; however, in the second case, that is compiled to the value, i.e. ifConstValue
happens to be123
, then the second is identical to:at runtime, the fact that it came from
SomeType
does not exist, as the value (123
) was evaluated by the compiler, and stored. Hence it needs a rebuild to pick up new values.Changing to
static readonly
means that the "load the value fromSomeType
" is preserved.So the following:
compiles as:
Note that in the
Bar
, theldc
is loading a value directly (0x1c8 == 456), withTest
completely gone.For completeness, the const is implemented with a static field, but - it is a literal field, meaning: evaluated at the compiler, not at runtime.
You have already answered your question with the image you linked to.
const
fields will be compiled ("inlined") into the assembly - like a simple search and replace.static readonly
means a normal field that is not allowed to change and exists only once in memory, but is still referenced by memory location.That is not the correct solution. If you change the value of a const then it was not a constant. Constants are by definition things that never change their value. The idea that you would change the value of a constant means that you are doing something logically impossible, and so of course things will break; you're doing something that you said you would not do. If you go around lying to the compiler, and it hurts when you do that, then stop lying to the compiler.
The price of gold is not a constant. The name of your bank is not a constant. The version number of your program is not a constant. These things change, so do not make them constants. Constants are things like pi, or the number of protons in an atom of gold.
Variables are things that can vary -- that's why they're called "variables". Constants are things that stay... constant. If it can vary, make it a variable. If it is constant, make it a constant. It is as simple as that.
Sure. What does that have to do with it? "static" in C# means "the named element is associated with the type, rather than with any particular instance of the type." ("Static" is therefore a poor choice of terms; VB does it better with "shared".)
Whether the name is associated with the type or an instance is irrelevant to the question of whether the name refers to a constant or variable.
When you use a constant value, the value is "baked in" wherever it is used. That's safe because it is never going to change. It's never going to change because it is constant, and that's what "constant" means.
When you use a variable, the variable's value is looked up at runtime every time. "readonly" just means "this variable can only be changed in the class constructor or field initializer". It is still a variable. (*)
You haven't stated what the problem is, so I don't know what problem you're trying to solve.
(*) Readonly fields are considered to be non-constant values outside the constructor, so that a readonly field of mutable value type cannot be mutated, and so that you cannot take a
ref
to a readonly field and then mutate the reference.I guess we can think of a constant as a hardcoded value in our code, but with better maintenance and usability offerings.