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
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 const
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 field is not a reference to anything; it is literal value "burned" into the code (using a const
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
:
- If you know the value will never, ever, ever change for any reason, use
const
. - 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
. - If you need a field to be a property of a type, and not a property of an instance of that type, use
static
. - A
const
value is also implicitlystatic
.
Hope that explains it better, Roger!
Happy Coding!
great article, please add a section talking about Get only properties and how they compare to these?
there are another static readonly advantages: you cant declare a DateTime const, but you can declare a static readonly DateTime.
Besides, static readonly properties can be changed in static class constructors (on your assembly's boot up)
Hi Matthew, thanks for explanation. But i am still confused with definition of Static. it said "A static member (variable, method, etc) belongs to the type of an object rather than to an instance of that type.", I am confused about "type of an object " and " an instance of that type".
if i see your sample, its like a static member belongs to a class itself and not belongs to object.
Static Method MyMethod() is belongs to class MyClass
Not belongs to object myClassObj
var myClassObj = new MyClass(); // myClassObj is an object = instance of class MyClass
var result = myClassObj.MyMethod(); //Will not compile
Can you help me explain about "type of an object " and " an instance of that type"?
Thanks before.
A static readonly variable can be written to by a static constructor. That is an important difference between a const variable and a static readonly variable. For example, the static constructor could detect the operating system version and store it into a static readonly variable.
Also a static variable example.
class Worker {
public static int workersCount = 0;
public Worker() { workersCount ++; }
}
var worker1 = new Worker();
var worker2 = new Worker();
var worker3 = new Worker();
Console.WriteLine("There are " + Worker.workersCount + " workers.")
> There are 3 workers.
how can you make use of Instance constructor to edit Static part in your above example? its wrong example provided by you.
Good explanation. Thanks!
Nice!
Roget is really happy now :D
Good explanation thanks.
Awesome!
Generally a good explanation, but it seems less than helpful to describe static in terms of a function when the rest are being described in terms of data.
I'd highlight the mutable nature of a static (and the one-and-only-one aspect) by something like the following...
A static member(etc) belongs to a type not an instance of a class, and so if we declare a static thus...
class x{
private static int y = 0;
public void sety(int newy){y=newy}
public int gety(return y}
}
...then if we create two objects as follows, setting y on each, we get the following effect...
a=new x();
b=new x();
a.gety(); //returns 0
b.gety(); //returns 0
a.sety(10);
a.gety(); //returns 10
b.gety(); //returns 10
... this is because there is only one variable y for the class x, not one per instance of the class.
This is very useful for creatings singletons (see https://en.wikipedia.org/wi...) but is a trap in many other cases.
Note, that despite being static, it is still mutable.
Kind of old, but justt read it.
I've found another difference, that might help you to decide what to use (depending on your needs)
1 - You cannot use static readonly properties in a "switch" statement.
2 - You cannot see how many references a "const" have.
My 2 cents :)
Awesome post, I'd add configuration stuff just to add to consideration though, since it's .Net specific talk. Most stuff people might do a const, it should also be considered for being an item in app.config, web.config. In the last paragraph you'd add: 5. "If you want the value to be configurable by administrators without re-compiling and deploying the code again, use config."
Hi, I have below scenario for Static and Const, if Const is by default static then why output is different in below scenario:
Scenario 1:
Defined const as below:
Compiler gave error "The evaluation of the constant value for 'AccessModifiers.Program.x' involves a circular definition"
Scenario 2:
Defined static as below and no error this time
private static int c = a;
Could you please help me find the answer.
um you might wanna slowly, carefully read your code
Great Explanation! sometime we forget the basics.. Thank you for a great refresher.
Thank you so much!
Redacted due to stupidity
Redacted due to stupidity
great post
Thank you!