I was performing some refactoring today and I've noticed a strange thing I can't understand...or better partially I agree with what I've found on the net but still have some questions.
Please consider this simple example
class Program
{
public static readonly string a = "a";
public const string b = "b";
static void Main(string[] args)
{
Console.WriteLine(a);
Console.WriteLine(b);
}
}
Now if I look at the generated IL Code (got via IL Browser from resharp)
I see the following code
.method private hidebysig static void
Main(
string[] args
) cil managed
{
.entrypoint
.maxstack 8
// [16 13 - 16 34]
IL_0000: ldsfld string ConsoleApp4.Program::a
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
// [18 13 - 18 34]
IL_000a: ldstr "b"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
// [19 9 - 19 10]
IL_0014: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0 // this
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
.method private hidebysig static specialname rtspecialname void
.cctor() cil managed
{
.maxstack 8
// [11 9 - 11 47]
IL_0000: ldstr "a"
IL_0005: stsfld string ConsoleApp4.Program::a
IL_000a: ret
} // end of method Program::.cctor
} // end of class ConsoleApp4.Program
For what concern the static string it behaves as I expected. Instead for the const it loads a new value on the stack... infact looking at the ldstr opcode here it says
Pushes a new object reference to a string literal stored in the metadata
I've read here that
Now, wherever myInt is referenced in the code, instead of having to do a "ldloc.0" to get the value from the variable, the MSIL just loads the constant value which is hardcoded into the MSIL. As such, there's usually a small performance and memory advantage to using constants.However, in order to use them you must have the value of the variable at compile time, and any references to this constant at compile time, even if they're in a different assembly, will have this substitution made.
Constants are certainly a useful tool if you know the value at compile time. If you don't, but want to ensure that your variable is set only once, you can use the readonly keyword in C# (which maps to initonly in MSIL) to indicate that the value of the variable can only be set in the constructor; after that, it's an error to change it. This is often used when a field helps to determine the identity of a class, and is often set equal to a constructor parameter.
But why should I experience a better performance? (even considering it's quite trascurable) ? What about memory footprint?
Thanks in advance