Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In .NET, why are constants evaluated at compile time rather than at JIT time?

Tags:

c#

.net

constants

I got a bit of a surprise today when I changed the value of a publicly-visible constant in a static class and then replaced an old copy of the assembly with the newly-compiled version. The surprise was that the existing program that referenced the assembly didn't pick up the new value of the constant. That is, I didn't re-compile the executable but rather just replaced that one assembly.

A full description of my experiment is at How constant is a constant?

I'll admit to being very surprised by this behavior. I understand what's going on, but I don't understand why. Is there a particular technical reason why constants couldn't be picked up at JIT time rather than compile time? Are there cases where doing that would break things?

like image 951
Jim Mischel Avatar asked Dec 10 '10 23:12

Jim Mischel


2 Answers

Constants are supposed to be constant. For all time. Constants are things like the value of pi, or the number of protons in a lead atom.

If your constant changes, it wasn't really a constant; use a readonly field instead.

Also see the Framework Design Guidelines, which state:

Use constant fields for constants that will never change. The compiler burns the values of const fields directly into calling code. Therefore const values can never be changed without the risk of breaking compatibility.

Essentially, changing a constant without recompiling everything that depends on it is every bit as broken as changing the signature of a method without recompiling everything that depends on it. The compiler "bakes in" all kinds of assumptions about information about metadata from referenced assemblies when it compiles a dependent assembly. If you make any change, you cannot expect things to simply keep on working.

like image 163
Eric Lippert Avatar answered Nov 09 '22 21:11

Eric Lippert


There is also a third way to declare "constants": a public static property.

public static string ConstString {get{return "First test";}}

This has the versioning semantics of a readonly field, but if the jitter inlines the getter it becomes a jit-time constant. And unlike const it can be used on user defined types.

I think it's a good idea to use static properties for value-types and string, but not for user defined classes, since you don't want to allocate a new instance on each property access.

I used this in my FixedPoint type like this:

public struct FixedPoint
{
  private int raw;
  private const fracDigits=16;

  private FixedPoint(int raw)
  {
    this.raw=raw;
  }

  public static FixedPoint Zero{get{return new FixedPoint();}}
  public static FixedPoint One{get{return new FixedPoint(1<<fracDigits);}}
  public static FixedPoint MaxValue{get{return new FixedPoint(int.MaxValue);}}
}
like image 1
CodesInChaos Avatar answered Nov 09 '22 21:11

CodesInChaos