Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant value not changing when recompiling referenced assembly

I have this code in an assembly:

public class Class1
{
    public const int x = 10;
}

and in a different assembly I have:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Class1.x);
        Console.ReadKey();
    }
}

Of course the output was 10, but then I changed x to 20:

public class Class1
{
    public const int x = 20;
}

I recompiled the assembly and moved it to my command line program's bin directory. However, the output of my program was still 10, until I compiled assembly containing the main function.

Why is this happening?

like image 686
No Idea For Name Avatar asked Jun 15 '14 08:06

No Idea For Name


People also ask

Does a constant change values during runtime?

As the name suggests, constants should not change during runtime and in my opinion constants are defined to not change for a long term (you may look at this SO question for more information.

Can you change a const C#?

Variables declared using the const keyword are also known as compile-time constants. It should be noted that a constant variable is immutable, i.e., the value assigned to a constant variable cannot be changed later.

How to declare constant in c sharp?

Constants are declared with the const modifier. Only the C# built-in types (excluding System. Object) may be declared as const . User-defined types, including classes, structs, and arrays, cannot be const .

How to use constant in C#?

The constants refer to fixed values that the program may not alter during its execution. These fixed values are also called literals. Constants can be of any of the basic data types like an integer constant, a floating constant, a character constant, or a string literal.


2 Answers

Constants values in C# are in-lined in place where they are used. I.e. line Console.WriteLine(Class1.x); will be compiled to Console.WriteLine(10);. Generated IL-code will look like:

  .entrypoint
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldc.i4.s   10  // here just integer value 10 is loaded on stack
  IL_0003:  call       void [mscorlib]System.Console::WriteLine(int32)

There will not be any link to Class1. So, until you re-compile Main assembly, it will have in-lined value 10. MSDN has warning about this case of constants usage:

Don’t create a constant to represent information that you expect to change at any time. For example, don’t use a constant field to store the price of a service, a product version number, or the brand name of a company. These values can change over time, and because compilers propagate constants, other code compiled with your libraries will have to be recompiled to see the changes.

They mention that constant expressions are evaluated only at compile time. I.e. Class1.x will be evaluated at Main assembly compile time to value 10. And without re-compilation that value will not change. But unfortunately it does not clearly explains reason of such behavior (to me at least).

BTW Named and Optional parameters values are also in-lined in place where method is called, and you also need to re-compile caller assembly to update values.

like image 186
Sergey Berezovskiy Avatar answered Sep 25 '22 18:09

Sergey Berezovskiy


This is a technique called constant folding used in compiling. In short, the compiler look for values that can be determined at compile time, computes those values, and write them directly in the exe file. This speeds up the execution of the final machine code. This technique applies to other many compiled languages, such as C, C++ as well.

like image 21
kevin Avatar answered Sep 25 '22 18:09

kevin