I'm continuing my study of C# and the language specification and Here goes another behavior that I don't quite understand:
The C# Language Specification clearly states the following in section 10.4:
The type specified in a constant declaration must be sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum-type, or a reference-type.
It also states in section 4.1.4 the following:
Through const declarations it is possible to declare constants of the simple types (§10.4). It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
Ok, so a similar effect can be gained by using static readonly. Reading this I went and tried the following code:
static void Main() { OffsetPoints(); Console.Write("Hit a key to exit..."); Console.ReadKey(); } static Point staticPoint = new Point(0, 0); static readonly Point staticReadOnlyPoint = new Point(0, 0); public static void OffsetPoints() { PrintOutPoints(); staticPoint.Offset(1, 1); staticReadOnlyPoint.Offset(1, 1); Console.WriteLine("Offsetting..."); Console.WriteLine(); PrintOutPoints(); } static void PrintOutPoints() { Console.WriteLine("Static Point: X={0};Y={1}", staticPoint.X, staticPoint.Y); Console.WriteLine("Static readonly Point: X={0};Y={1}", staticReadOnlyPoint.X, staticReadOnlyPoint.Y); Console.WriteLine(); }
The output of this code is:
Static Point: X=0;Y=0
Static readonly Point: X=0;Y=0
Offsetting...
Static Point: X=1;Y=1
Static readonly Point: X=0;Y=0
Hit a key to exit...
I really expected the compiler to give me some kind of warning about mutating a static readonly field or failing that, to mutate the field as it would with a reference type.
I know mutable value types are evil (why did Microsoft ever implement Point
as mutable is a mystery) but shouldn't the compiler warn you in some way that you are trying to mutate a static readonly value type? Or at least warn you that your Offset()
method will not have the "desired" side effects?
The first, const, is initialized during compile-time and the latter, readonly, initialized is by the latest run-time. The second difference is that readonly can only be initialized at the class-level. Another important difference is that const variables can be referenced through "ClassName.
readonly keyword is used to define a variable which can be assigned once after declaration either during declaration or in constructor. const keyword is used to define a constant to be used in the program.
Constant and ReadOnly keyword is used to make a field constant which value cannot be modified. The static keyword is used to make members static that can be shared by all the class objects.
A const is a compile-time constant whereas readonly allows a value to be calculated at run-time and set in the constructor or field initializer. So, a 'const' is always constant but 'readonly' is read-only once it is assigned.
Eric Lippert explains what's going on here:
...if the field is readonly and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the field I in the object referenced by E.
The important word here is that the result is the value of the field, not the variable associated with the field. Readonly fields are not variables outside of the constructor. (The initializer here is considered to be inside the constructor; see my earlier post on that subject.)
Oh and just to stress on the evilness of mutable structs, here is his conclusion:
This is yet another reason why mutable value types are evil. Try to always make value types immutable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With