'Static readonly' vs. 'const'

Viewed 442661

I've read around about const and static readonly fields. We have some classes which contain only constant values. They are used for various things around in our system. So I am wondering if my observation is correct:

Should these kind of constant values always be static readonly for everything that is public? And only use const for internal/protected/private values?

What do you recommend? Should I maybe even not use static readonly fields, but rather use properties maybe?

22 Answers

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.

I would use static readonly if the Consumer is in a different assembly. Having the const and the Consumer in two different assemblies is a nice way to shoot yourself in the foot.

A few more relevant things to be noted:

const int a

  • must be initialized.
  • initialization must be at compile time.

readonly int a

  • can use a default value, without initializing.
  • initialization can be done at run time (Edit: within constructor only).

One thing to note is const is restricted to primitive/value types (the exception being strings).

My preference is to use const whenever I can, which, as mentioned in previous answers, is limited to literal expressions or something that does not require evaluation.

If I hit up against that limitation, then I fallback to static readonly, with one caveat. I would generally use a public static property with a getter and a backing private static readonly field as Marc mentions here.

Const: Constant variable values have to be defined along with the declaration and after that it won't change.const are implicitly static, so without creating a class instance we can access them. This has a value at compile time.

ReadOnly: We can define read-only variable values while declaring as well as using the constructor at runtime. Read-only variables can't access without a class instance.

Static readonly: We can define static readonly variable values while declaring as well as only through a static constructor, but not with any other constructor. We can also access these variables without creating a class instance (as static variables).

Static readonly will be better choice if we have to consume the variables in different assemblies. Please check the full details in the below blog post:

Const Strings – a very convenient way to shoot yourself in the foot

A const (being determined at compile-time) can be used in cases where a readonly static can't, like in switch statements, or attribute constructors. This is because readonly fields are only resolved at run-time, and some code constructs require compile time assurance. A readonly static can be calculated in a constructor, which is often an essential and useful thing. The difference is functional, as should be their usage in my opinion.

In terms of memory allocation, at least with strings (being a reference type), there seems to be no difference in that both are interned and will reference the one interned instance.

Personally, my default is readonly static, as it makes more semantic and logical sense to me, especially since most values are not needed at compile time. And, by the way, public readonly statics are not unusual or uncommon at all as the marked answer states: for instance, System.String.Empty is one.

Another difference between declaring const and static readonly is in memory allocation.

A static field belongs to the type of an object rather than to an instance of that type. As a result, once the class is referenced for the first time, the static field would "live" in the memory for the rest of time, and the same instance of the static field would be referenced by all instances of the type.

On the other hand, a const field "belongs to an instance of the type.

If memory of deallocation is more important for you, prefer to use const. If speed, then use static readonly.

Use const if you can provide a compile-time constant:

private const int Total = 5;

Use static readonly if you need your value evaluated during run-time:

private static readonly int GripKey = Animator.StringToHash("Grip");

This will give a compile error because it is impossible to get the value at compile-time.

private const int GripKey = Animator.StringToHash("Grip");

There is one important question, that is not mentioned anywhere in the above answers, and should drive you to prefer "const" especially for basic types like "int", "string" etc.

Constants can be used as Attribute parameters, static readonly field not!

Azure functions HttpTrigger, not using HttpMethods class in attribute

If only microsoft used constants for Http's GET, POST, DELETE etc.

It would be possible to write

[HttpTrigger(AuthorizationLeve.Anonymous,  HttpMethods.Get)] // COMPILE ERROR: static readonly, 

But instead I have to resort to

[HttpTrigger(AuthorizationLeve.Anonymous,  "GET")] // STRING

Or use my own constant:

public class HttpConstants
{
    public const string Get = "GET";
}

[HttpTrigger(AuthorizationLeve.Anonymous,  HttpConstants.Get)] // Compile FINE!

Const

  1. Can be applied only for fields. Value should be in code compile time.
  2. Suited for removing magic "strings","int/double", (primitive types) etc across the code which is known already before compiling the code.
  3. After compiling the value will be placed all over the compiled code wherever constant is used. So if you have a huge string used many places, then watch out before making it const. consider using static read only.

Static read only

  1. Static read only be applied for fields/props and static can be used for methods. (on side note)When static is applied to methods, the complied code does not pass the 'this' parameter to the method and hence you cannot access the instance data of the object.
  2. Suitable for values which may change after compiling the code. Like values initialized from configuration, during startup of application etc.
  3. After compiling the code, the ref to value is used in IL code and may be slower compared to using const, but compiled code is small

During Refactoring, All const can be safely converted to Static read only, but not vise versa as we have seen above when converted code may break as some static readonly variable could be initialized in constructors.

One additional difference that I don't believe is mentioned above:

const and static readonly values don't get CodeLens applied to them in the Visual Studio IDE.

static get only properties DO get CodeLens applied to them.

Code Lens Example

I consider the addition of CodeLens to be quite valuable.

Note: Currently using Visual Studio 2022.

Const, readonly, static readonly - keywords that perform a similar action but have an important difference:

Const - is a variable whose value is constant and is assigned at compile time. You must assign a value to it. The default constants are static, and we cannot change the value of the const variable throughout the program.

Readonly - means a value that we can change at run time, or we can assign it at run time, but only through a non-static constructor.

Static readonly - values ​​can be assigned at run time or assigned at compile time and changed at run time. But the value of this variable can be changed only in the static constructor. And cannot be changed further. It can only be changed once during execution.

Examples you can find here - https://www.c-sharpcorner.com/UploadFile/c210df/difference-between-const-readonly-and-static-readonly-in-C-Sharp/

Related