I've read around about const
and static readonly
fields. We have some classes which contains only constant values. 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?
My preference is to use const whenever I can, which as mentioned above is limited to literal expressions or something that does not require evaluation.
If I hot 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.
One thing to note is const is restricted to primitive/value types (the exception being strings)
Static Read Only : Value can be changed through
static
constructor at runtime. But not through member Function.Constant : By default
static
. Value cannot be changed from anywhere (Ctor, Function, runtime etc no-where).Read Only : Value can be changed through constructor at runtime. But not through member Function.
You can have a look at my repo : C# property types.
There is a minor difference between const and static readonly fields in C#.Net
const must be initialized with value at compile time.
const is by default static and needs to be initialized with constant value, which can not be modified later on. It can not be used with all datatypes. For ex- DateTime. It can not be used with DateTime datatype.
readonly can be declared as static, but not necessary. No need to initialize at the time of declaration. Its value can be assigned or changed using constructor once. So there is a possibility to change value of readonly field once (does not matter, if it is static or not), which is not possible with const.
A static readonly field is advantageous when exposing to other assemblies a value that might change in a later version.
For instance, suppose assembly
X
exposes a constant as follows:If assembly
Y
referencesX
and uses this constant, the value 2.3 will be baked into assemblyY
when compiled. This means that ifX
is later recompiled with the constant set to 2.4,Y
will still use the old value of 2.3 untilY
is recompiled. A static readonly field avoids this problem.Another way of looking at this is that any value that might change in the future is not constant by definition, and so should not be represented as one.
const
andreadonly
are similar, but they are not exactly the same.A
const
field is a compile-time constant, meaning that that value can be computed at compile-time. Areadonly
field enables additional scenarios in which some code must be run during construction of the type. After construction, areadonly
field cannot be changed.For instance,
const
members can be used to define members like:Since values like 3.14 and 0 are compile-time constants. However, consider the case where you define a type and want to provide some pre-fab instances of it. E.g., you might want to define a Color class and provide "constants" for common colors like Black, White, etc. It isn't possible to do this with const members, as the right hand sides are not compile-time constants. One could do this with regular static members:
But then there is nothing to keep a client of Color from mucking with it, perhaps by swapping the Black and White values. Needless to say, this would cause consternation for other clients of the Color class. The "readonly" feature addresses this scenario.
By simply introducing the
readonly
keyword in the declarations, we preserve the flexible initialization while preventing client code from mucking around.It is interesting to note that const members are always static, whereas a readonly member can be either static or not, just like a regular field.
It is possible to use a single keyword for these two purposes, but this leads to either versioning problems or performance problems. Assume for a moment that we used a single keyword for this (const) and a developer wrote:
and a different developer wrote code that relied on A:
Now, can the code that is generated rely on the fact that A.C is a compile-time constant? I.e., can the use of A.C simply be replaced by the value 0? If you say "yes" to this, then that means that the developer of A cannot change the way that A.C is initialized -- this ties the hands of the developer of A without permission.
If you say "no" to this question then an important optimization is missed. Perhaps the author of A is positive that A.C will always be zero. The use of both const and readonly allows the developer of A to specify the intent. This makes for better versioning behavior and also better performance.