20

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:

enter image description here

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 conststatic?

2) Where actually the values are saved ?

3) How does making a field static readonly actually solve this problem "behind the scene" ?

2
  • 2
    It's because the compiler will "inline" the value of the constant, instead of referencing a variable that comes from another assembly.
    – ken2k
    Commented Feb 2, 2012 at 9:09
  • 2
    Never knew of this behavior of consts between the assemblies. Good question Commented Feb 2, 2012 at 12:09

5 Answers 5

26

if you change the value of a const, you need to rebuild all the clients

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.

why is that? both static readonly and const are static

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.

where actually the values is being saved in both static readonly vsconst ?

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. (*)

how making a field static readonly - actually solve this problem behind the scene ?

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.

4
  • 1
    Now I understand what this sentence means!: If you lie to the compiler, it will get its revenge --Henry Spencer
    – Ayub
    Commented Aug 23, 2015 at 6:01
  • Your writing is very good. Why not write a great book about C#. it is my dream!
    – Ayub
    Commented Aug 23, 2015 at 6:06
  • 1
    @programmer1: Thanks! I helped Mark out in writing the last couple editions of Essential C#, but most of the writing is his. I've thought about writing a C# book of my own, but it is a lot of work. Also, I write a blog about the design of C#. Commented Aug 23, 2015 at 14:26
  • The problem I have with this answer is that it assumes a meaning for "change the value of a constant" that I believe contradicts what @marc Gravell had in mind. I understood him to mean "change the value of const XYZ to mean that you change the value of const XYZ in assembly A, which is referenced in assembly B. When Assembly B is built, the value that XYZ has in assembly A is baked into assembly B. If you subsequently change the value of XYZ in assembly A and rebuild it, assembly B still sees the old value. Commented Jun 19, 2021 at 20:57
25

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:

var foo = SomeType.StaticValue;

vs

var bar = SomeType.ConstValue;

in the first case, it reads the value at runtime from SomeType, i.e. via a ldsfld; however, in the second case, that is compiled to the value, i.e. if ConstValue happens to be 123, then the second is identical to:

var bar = 123;

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 from SomeType" is preserved.

So the following:

static int Foo()
{
    return Test.Foo;
}
static int Bar()
{
    return Test.Bar;
}
...
static class Test
{
    public static readonly int Foo = 123;
    public const int Bar = 456;
}

compiles as:

.method private hidebysig static int32 Bar() cil managed
{
    .maxstack 8
    L_0000: ldc.i4 0x1c8
    L_0005: ret 
}

.method private hidebysig static int32 Foo() cil managed
{
    .maxstack 8
    L_0000: ldsfld int32 ConsoleApplication2.Test::Foo
    L_0005: ret 
}

Note that in the Bar, the ldc is loading a value directly (0x1c8 == 456), with Test 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.

.field public static literal int32 Bar = int32(0x1c8)
.field public static initonly int32 Foo
2
  • thank for excellent answer , but isnt const is implicitly static ?
    – Royi Namir
    Commented Feb 2, 2012 at 9:24
  • 1
    @Royi well, yes in so much as it is implemented in the IL as a .field ... static, and in the C# accessed as TypeName.ConstName - but the important thing is the semantics; and in terms of the what the semantics mean, there's a huge difference between accessing a regular static member (field/prop) and accessing a const member. Commented Feb 2, 2012 at 9:30
6

1) const is just resolved during compile time with the value that you have provided. While static 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.

4

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.

In the .NET Framework, constants are not assigned a memory region, but are instead considered values. Therefore, you can never assign a constant, but loading the constant into memory is more efficient because it can injected directly into the instruction stream. This eliminates any memory accesses outside of the memory, improving locality of reference. http://www.dotnetperls.com/optimization

1

I guess we can think of a constant as a hardcoded value in our code, but with better maintenance and usability offerings.

Not the answer you're looking for? Browse other questions tagged or ask your own question.