Static Readonly' Vs. 'Const'

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 VS readonly values can be computed dynamically but need to be assigned before the constructor exits.. after that it is frozen.
  • const's are implicitly static. You use a ClassName.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' the AssemblyB's IL. This means that if tomorrow I update I_CONST_VALUE to 20, AssemblyB would still have 2 till I recompile it.
  • in the case of the readonly value, it is like a ref to a memory location. The value is not baked into AssemblyB's IL. This means that if the memory location is updated, AssemblyB gets the new value without recompilation. So if I_RO_VALUE is updated to 30, you only need to build AssemblyA 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



Leave a reply



Submit