Static readonly' vs. 'const'
public static readonly
fields are a little unusual; public static
properties (with only a get
) would be more common (perhaps backed by a private static readonly
field).
const
values are burned directly into the call-site; this is double edged:
- it is useless if the value is fetched at runtime, perhaps from config
- if you change the value of a const, you need to rebuild all the clients
- but it can be faster, as it avoids a method call...
- ...which might sometimes have been inlined by the JIT anyway
If the value will never change, then const is fine - Zero
etc make reasonable consts ;p Other than that, static
properties are more common.
what is the difference between const, readonly and get in a static class
The member declared as readonly gives the possibility to be changed in the (static) constructor of the class, while the const member cannot be changed at runtime.
Declaring a field as const makes it automatically static, quoting from §10.3.7:
When a field, method, property, event, operator, or constructor
declaration includes a static modifier, it declares a static member.
In addition, a constant or type declaration implicitly declares a
static member.
The third is just a read-only property which happens to always return 5.
You should never use such a property and prefer const members where possible in order to allow the compiler and/or the jitter to perform their optimizations and to help other people reading your code (that property is kind of a WTF to me). The static readonly member has to be used if it is required a constant value initialized during the program start-up (like, for example, the number of cores of a machine).
This is a great example from the C# specs (§10.5.2.1):
A static readonly field is useful when a symbolic name for a constant
value is desired, but when the type of the value is not permitted in a
const declaration, or when the value cannot be computed at
compile-time. In the example
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
the Black, White, Red, Green, and Blue members cannot be declared as
const members because their values cannot be computed at compile-time.
However, declaring them static readonly instead has much the same
effect.
And yet another difference (§10.5.2.2):
Constants and readonly fields have different binary versioning
semantics. When an expression references a constant, the value of the
constant is obtained at compile-time, but when an expression
references a readonly field, the value of the field is not obtained
until run-time.
So, summing it up, they are very different even if at a first glance they might look similar and you should use the one which best suits your intent.
const vs. static readonly
I don't know about your second item (I would probably use a constant for a software version or an algorithm… constant) but there is one key difference between the two: const
can only hold basic types such as string
, bool
, or numeric types. static readonly
can hold any object. So, for example, I often use static readonly
to store resources like Bitmap
objects. Those cannot be const
.
What is the difference between const and readonly in C#?
Apart from the apparent difference of
- having to declare the value at the time of a definition for a
const
VSreadonly
values can be computed dynamically but need to be assigned before the constructor exits.. after that it is frozen. const
's are implicitlystatic
. You use aClassName.ConstantName
notation to access them.
There is a subtle difference. Consider a class defined in AssemblyA
.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
references AssemblyA
and uses these values in code. When this is compiled:
- in the case of the
const
value, it is like a find-replace. The value 2 is 'baked into' theAssemblyB
's IL. This means that if tomorrow I updateI_CONST_VALUE
to 20,AssemblyB
would still have 2 till I recompile it. - in the case of the
readonly
value, it is like aref
to a memory location. The value is not baked intoAssemblyB
's IL. This means that if the memory location is updated,AssemblyB
gets the new value without recompilation. So ifI_RO_VALUE
is updated to 30, you only need to buildAssemblyA
and all clients do not need to be recompiled.
So if you are confident that the value of the constant won't change, use a const
.
public const int CM_IN_A_METER = 100;
But if you have a constant that may change (e.g. w.r.t. precision).. or when in doubt, use a readonly
.
public readonly float PI = 3.14;
Update: Aku needs to get a mention because he pointed this out first. Also I need to plug where I learned this: Effective C# - Bill Wagner
Static readonly vs const — different assemblies POV?
no, a const is a const, not a static - it is a special-case, with different rules; it is only set at compile-time (not runtime), and it is handled differently
the crux here is what the following means:
var foo = SomeType.StaticValue;
vs
var bar = SomeType.ConstValue;
in the first case, it reads the value at runtime from SomeType
, i.e. via a ldsfld
; however, in the second case, that is compiled to the value, i.e. if ConstValue
happens to be 123
, then the second is identical to:
var bar = 123;
at runtime, the fact that it came from SomeType
does not exist, as the value (123
) was evaluated by the compiler, and stored. Hence it needs a rebuild to pick up new values.
Changing to static readonly
means that the "load the value from SomeType
" is preserved.
So the following:
static int Foo()
{
return Test.Foo;
}
static int Bar()
{
return Test.Bar;
}
...
static class Test
{
public static readonly int Foo = 123;
public const int Bar = 456;
}
compiles as:
.method private hidebysig static int32 Bar() cil managed
{
.maxstack 8
L_0000: ldc.i4 0x1c8
L_0005: ret
}
.method private hidebysig static int32 Foo() cil managed
{
.maxstack 8
L_0000: ldsfld int32 ConsoleApplication2.Test::Foo
L_0005: ret
}
Note that in the Bar
, the ldc
is loading a value directly (0x1c8 == 456), with Test
completely gone.
For completeness, the const is implemented with a static field, but - it is a literal field, meaning: evaluated at the compiler, not at runtime.
.field public static literal int32 Bar = int32(0x1c8)
.field public static initonly int32 Foo
Declaring strings public static readonly versus public const versus public static const
I don't understand what the performance implications are between the different declarations
The cost of evaluating the database query is probably going to be millions or billions of times the cost difference of changing from a constant to a readonly field or vice versa. Don't even worry about performance of something that takes a couple of nanoseconds when you have database operations that have latency measured in milliseconds.
What you should be worrying about is semantics, not performance. The question boils down to "readonly, constant or neither?"
Get the semantics right. A "readonly" field means "this field changes exactly once per time this program is executed", from null to its value. A "const" field means "this value never changes, not now, not in the next version, not ever, it is constant for all time." An ordinary field can change value at any time.
A readonly field is something like a version number. It changes over time, but does not change over the execution of the program. A constant is something like pi, or the atomic number of lead; it is fixed, eternal, never changes. An ordinary field is good for something that changes over the course of the program, like the price of gold. Which is your query like? Will it be constant throughout the course of this program, constant for all time, or not constant at all?
Const vs protected static readonly
If you want to change the value of these params in a derived class, you can make them readonly and change them in the constructor of the derived class
I wouldn't make them const anyhow, because they're not...
Which is preferable: const or static readonly?
const if you know the value before compile time.
Related Topics
C# Json.Net Convention That Follows Ruby Property Naming Conventions
How to Run a Python Script from C#
How to Make a Textbox That Only Accepts Numbers
How to Use Reflection to Call a Generic Method
Captured Variable in a Loop in C#
How to Properly Clean Up Excel Interop Objects
How to Detect Click/Touch Events on Ui and Gameobjects
How to Configure an App to Run Correctly on a Machine With a High Dpi Setting (E.G. 150%)
Dynamic Linq Orderby on Ienumerable≪T≫/Iqueryable≪T≫
Communicate Between Two Windows Forms in C#
Parsing CSV Files in C#, With Header
Split List into Sublists With Linq
Elevating Process Privilege Programmatically
Dependency Inject (Di) "Friendly" Library