Just last week I had a new-to-ASP.NET developer (we'll call him Roger) ask me to explain what the difference was between a variable declared as const variable and that same variable declared as static readonly. I made some stuff up tried my best to break it down, but I don't think I did a good enough job. As many of my readers know, I don't enjoy being unable to explain things well.

So, Roger, this post is my official, on-the-record attempt at getting you an answer to your question. Let's find out what the difference is between const, readonly and static variables in C#, and when we should use each of these keywords.

Const

A variable declared as const (read: constant) must be assigned a value at declaration, and this value may not then change at a later time.

public const string ConnectionString = "YourConnectionString";  

The value in a const variable is what's called a "compile-time" value, and is immutable (which means it does not change over the life of the program).

Only primitive or "built-in" C# types (e.g. int, string, double) are allowed to be declared const. Therefore, you cannot write either of these:

public const DateTime DeclarationOfIndependence = new DateTime(1776,7,4);  
public const MyClass MyValue = new Class() {Name = "TestName"};  

You want to use const when you have a variable whose value will not change, ever, during the time your application is being used. Further, any variable declared as const will also, implicitly, be declared static.

But that begs the question: what does static do?

Static

A static member (variable, method, etc) belongs to the type of an object rather than to an instance of that type. Hence, if we declare this:

public class MyClass  
{
    public static string MyMethod() { ... }
}

We must call this method like this:

var result = MyClass.MyMethod();  

We will NOT be able to make calls like this:

var myClass = new MyClass();  
var result = myClass.MyMethod(); //Will not compile  

Now there's only one keyword left to define: readonly.

Readonly

A readonly field is one where assignment to that field can only occur as part of the declaration of the class or in a constructor.

public class TestClass  
{
    public readonly string ConnectionString = "TestConnection";

    public TestClass()
    {
        ConnectionString = "DifferentConnection";
    }

    public void TestMethod ()
    {
        ConnectionString = "NewConnection";//Will not compile
    }
}

This means that a readonly variable can have different values for different constructors in the same class.

Const vs. Static Readonly

Now we get back to the question Roger originally asked: what is the difference between a variable declared as const and the same variable declared as static readonly?

First, what are the properties of a static readonly variable?

  • It cannot be changed outside of its declaration or containing class's constructor (due to readonly).
  • It is part of the type, not part of an instance of that type (due to static).

At first glance this sounds a lot like a constant field, since a constant can only be given a value at its declaration and cannot have that value changed anywhere else. The difference lies in the details.

First, a const variable is not a reference to anything; it is literal value "burned" into the code (using a constant is the true definition of hard coding a value). A static readonly variable is a reference, and consequently a lookup is performed any time this variable is accessed. However, as often happens, the compiler is smarter than you and any supposed performance difference will probably be negated.

But there's another, more subtle difference that we should be aware of. If a const variable exists in Assembly A and is used in Assembly B, when Assembly A gets recompiled with a new value for the const variable Assembly B will still have the previous value until it is also recompiled.

Consider the following class, defined in Assembly A:

public class GeneralData  
{
    public const int CONSTANT_NUMBER = 6;
}

Imagine that we also have Assembly B, another class library that references Assembly A and uses CONSTANT_NUMBER. Let's say we change this value in Assembly A, like so:

public class GeneralData  
{
    public const int CONSTANT_NUMBER = 90;
}

We then recompile Assembly A and deploy it, and it will have the new value for CONSTANT_NUMBER. Problem is, Assembly B will still have the value be 6 because it has not been recompiled to include the new value. Here's the original StackOverflow answer explaining this phenomenon.

Summary

Here's what you need to know about using const, static, and readonly:

  1. If you know the value will never, ever, ever change for any reason, use const.
  2. If you're unsure of whether or not the value will change, but you don't want other classes or code to be able to change it, use readonly.
  3. If you need a field to be a property of a type, and not a property of an instance of that type, use static.
  4. A const value is also implicitly static.

Hope that explains it better, Roger!

Happy Coding!