const vs. static readonly

The problem
I was recently working on an application that relied on a common library stored in the server’s GAC. The application is using constants that are defined in the common library and have different values depending on the environment the application is being deployed to (Dev, Test or Prod). Everything worked fine in our Dev environment but while debugging our code in Test, we found out that it was using the Dev values of the constants instead of the Test values even though the common library stored in the GAC was correct.

Why is it happening?
The cause of this problem is due to the way constants are treated at compile time. Let’s look at the following code:

const string MY_CONSTANT = “My Dev value”;

if (common.MY_CONSTANT == “My Dev value”) {…}

The .Net compiler substitutes the constant name with its actual value in app so this would actually be equivalent to writing:

if (“My Dev value” == “My Dev value”) {…}

which is the code that will be converted to IL. As a result, it doesn’t matter what the value of the constant is in the dll that has been placed in the GAC because this value will not be read at run-time.

The solution
One of the ways to solve this would be to change the constants values each time the application is being built for a certain environment. This approach creates a build management nightmare and adds complexity when there is no need for it.

A second approach would be to remove the const keyword so the variable is not being substituted for its value at compile time but this would break the design and make for very bad coding practice.

The right way to handle this is to use the static readonly keywords. A static readonly variable can be initialized at declaration time or in a static constructor so the compiler does not know its value at compile time. As a result, there is no substitution and the value will be read at run-time. The fact that the variable is read-only allows to make sure that it has a similar behavior to a constant once initialized.
Besides the added flexibility for initialization, another benefit of a static readonly variable is that it can hold reference types other than string or null as const only can.