4

Why are const usages replaced by their values on compile time but then still included in the assembly? At least this is what IL DASM and Reflector shows.

Currently I am using const for defining many magic numbers and strings to easier be able to change code without affecting run-time performance.

Now I know that that doesnt affect the used memory but it still affects compiled assembly size which is crucial for example for mobile phone apps.

Another disadvantage is that other people easier understand magic numbers when looking at the disassembled code.

I am really interested in why the compiler (Mono as well as .NET) does this exactly?

stfx
  • 149
  • 8

2 Answers2

6

This behaviour is specified in the ECMA-335 standard (of which both .NET and Mono are implementations). Citing from section II.22.9, "Constant":

Note that Constant information does not directly influence runtime behavior, although it is visible via Reflection (and hence can be used to implement functionality such as that provided by System.Enum.ToString). Compilers inspect this information, at compile time, when importing metadata, but the value of the constant itself, if used, becomes embedded into the CIL stream the compiler emits. There are no CIL instructions to access the Constant table at runtime.

That is, const values are "inlined" (possibly because they can be, and for performance reasons), but are kept in metadata nevertheless so they can be inspected by compilers and tools.

If no metadata were emitted for the const-ness of fields, this would have these consequences (possibly among others — these are just two examples):

  • Compilers or tools like Reflector could no longer distinguish between regular fields and const fields.
  • If you inspected a field using System.Reflection, you would no longer be able to use the FieldInfo.IsLiteral property.
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • +1 Still I am not sure how that would raise eyebrows since I for one did not expected to find `const` fields via Reflection. Also amusingly `System.Enum.ToString` is probably the slowest implementation to get the enum string representation. But I guess if ECMA says so.. – stfx Apr 06 '13 at 10:13
  • @stfx: I was mistaken with the last part of my answer. It's not that `const` fields would no longer be discoverable through metadata; you would just not be able to distinguish them from regular fields. I've corrected my answer. – stakx - no longer contributing Apr 06 '13 at 10:42
2

The increased assembly size is basically due to the C# compiler emitting additional metadata about const-ness.


What output would you expect from this short program?

class Program
{
    public const int C = 0;
    public       int F = 0;

    static void Main(string[] args)
    {
        foreach (FieldInfo field in typeof(Program).GetFields())
        {
            Console.WriteLine("{0}: IsLiteral = {1}", field.Name, field.IsLiteral);
        }
    }
}

The actual output is:

C: IsLiteral = True
F: IsLiteral = False

Which matches the declarations in the C# source exactly: Two fields, one of them const.

Now let's say that the C# compiler had decided not to emit Constant metadata. Then the output would be:

C: IsLiteral = False
F: IsLiteral = False

Which is clearly incorrect when compared to the C# source code, because now both fields appear as non-const.

Finally, let's say that the C# compiler had decided not to emit any metadata for C at all (since it "inlines" the field's value anyway):

F: IsLiteral = False

This is also incorrect, since reflection no longer reports the existence of a field which is clearly there in the C# source code. At least for me, that would be a good moment for some eyebrow-raising.

These counter-examples should make it clear why it is a good thing that complete metadata is emitted even for const fields.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • Thanks for clarifying. I would have preferred if they were handled similar to c++ #defines as in not really being fields, not being compiled, and reflection not returning them but I guess the designers wanted that reflection support ;) – stfx Apr 06 '13 at 11:32