I am comparing constants to static readonly class fields because they are used in the same way.
At a high level, constants are obviously dealt with at compile-time, while static readonly fields are set at the time they are evaluated at run-time. The fact that constant values are subsituted by the compiler means that any library/assembly which references the constant value will need to be recompiled if the constant value changes. Libraries referencing a static readonly field will reference the field and not the value, thus they will pick up any change in the field without the need for recompilation. So constants 0 - static readonly 1 in the area of maintainability.
Static readonly fields are able to hold reference types whereas constants will only support value types plus the special .NET ones string and null.
Finally, readonly fields can be set wherever and however the developer chooses meaning they can be lazy-loaded, and they can contain calculated values. A use for this that I found was when I was developing a system which could potentially use multiple databases. I needed the maximum permissible date from Oracle and Sql Server. Based on application configuration I was able to calculate this at runtime and still store the value in a static readonly field in the static Constants class along with regular constant values.
So, it appears that constants should be used when it is very unlikely that the value will ever change, or if no external apps/libs will be using the constant. Static readonly fields should be used when run-time calculation is required, or if external consumers are a factor.
This source code below is an example of the difference between const and readonly. Say you created a file A.cs and then compiled it to A.dll. Then you write your main application called MyTest.cs. After compiling MyTest.cs with referencing A.dll, you run the MyTest.exe.
Using System;
public class A
{
public const int X = 123;
}
csc /t:library /out:A.dll A.cs
using System;
public class MyTest
{
public static void Main()
{
Console.WriteLine("X value = {0}", A.X);
}
}
csc /r:A.dll MyTest.cs
To run: mytest
The output :
X value = 123
Then you install the program into your client computer. It runs perfectly.
One week later, you realised that the value of X should have been 812 instead of 123.
What you will need to do is to
1] Compile A (after making the changes)
csc /t:library /out:A.dll A.cs
2] Compile your application again
csc /r:A.dll MyTest.cs
This can be a little troublesome. However, if you used the readonly instead of const,the situation will be slightly different. You start with
using
System;
public class A
{
public static readonly int X = 123;
}
csc /t:library /out:A.dll A.cs
using System;
public class MyTest
{
public static void Main()
{
Console.WriteLine("X value = {0}", A.X);
}
}
csc /r:A.dll MyTest.cs
To run: mytest
The output :
X value = 123
Now you realised, you have made a mistake. All you need to do is
1] Recompile A.cs (after making changes)
csc /t:library /out:A.dll A.cs
2] Copy the new dll to the client computer and it should run perfectly. There is no need to recompile your application MyTest.cs here