readonly Keyword
This page was last reviewed on Jul 4, 2021.
Dot Net Perls
Readonly. This C# keyword prevents a class field from being changed. Readonly fields can be initialized at runtime, unlike const values.
This C# modifier does not affect performance. It just enforces certain constraints in the compiler. This leads to greater program quality.
An example. Here we use the readonly keyword to initialize a DateTime struct. We cannot set a const DateTime—this raises a compilation error.
Important In this example, we want to designate a DateTime field as unavailable for further changes.
Detail In the constructor, the startup time is initialized. We can assign the readonly field here.
Tip The benefit here is that other code, or the code from team members, can't change the readonly field.
And This makes it less likely to be messed up by someone who doesn't understand its purpose.
using System; class Program { static void Main() { Manager manager = new Manager(); Console.WriteLine(manager.GetStartup()); } } class Manager { readonly DateTime _startup; // <-- the readonly field public Manager() { // Initialize startup time. this._startup = DateTime.Now; } public DateTime GetStartup() { // We cannot modify the DateTime here. return this._startup; } }
(Current time)
Inline initialization. It is possible to use an inline initialization for readonly. In IL Disassembler we see the compiler has put it in the constructor itself.
class Manager { readonly DateTime _startup = DateTime.Now; public DateTime GetStartup() { return this._startup; } }
Error. One mistake you might make when using readonly is trying to assign to it in a place that is not a constructor. This will result in the following ugly error when you try to compile.
Detail A readonly field cannot be assigned to (except in a constructor or a variable initializer).
class Program { static readonly int _code = 100; static void Main() { _code = 200; } }
Error CS0198 A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)
Public static readonly. Public static readonly fields are recommended. They are used for types that cannot be represented as const values, but are not subject to change during execution.
Note The C# specification recommends public static readonly fields when we cannot use a const field or when the field may change.
Tip Readonly fields are as fast as other fields. But const values are faster—they are inserted directly into the locations where used.
Tip 2 Add the System.Drawing assembly reference to compile this program. This can be done though Visual Studio's menus.
using System; using System.Drawing; static class Points { // // Defines four public static readonly fields on a static class. // public static readonly Point TopLeft = new Point(0, 0); public static readonly Point TopRight = new Point(1, 0); public static readonly Point BottomRight = new Point(1, 1); public static readonly Point BottomLeft = new Point(0, 1); // public const Point TopLeft = new Point(0, 0); } class Program { static void Main() { // // Uses the public static readonly fields. // Console.WriteLine(Points.TopLeft); Console.WriteLine(Points.TopRight); Console.WriteLine(Points.BottomRight); Console.WriteLine(Points.BottomLeft); // Points.TopLeft = new System.Drawing.Point(); } }
{X=0,Y=0} {X=1,Y=0} {X=1,Y=1} {X=0,Y=1}
Notes, public static readonly. We can get an error from using public static readonly (or const) fields. Here are some errors that can be encountered.
Info The concept of using public static readonly fields to simulate constant class instances is shown in the C# specification itself.
A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)
The type 'System.Drawing.Point' cannot be declared const
Benchmark, readonly. Consider this simple benchmark of readonly and const ints. We try to determine if there is any performance benefit to using readonly (or avoiding it).
Version 1 This version of the code gets a readonly field from the class many times in a loop.
Version 2 Here we get an int field that is not readonly many times in a tight loop.
Detail We fetch a const value in the loop. So no field needs to be accessed in this version.
Result Using a field that is not readonly appears to be fastest. But logically the const should be as fast as anything.
using System; using System.Diagnostics; class Test { readonly int _value1; int _value2 = 1; const int _value3 = 1; public Test() { _value1 = int.Parse("1"); } public int GetValue1() { return _value1; } public int GetValue2() { return _value2; } public int GetValue3() { return _value3; } } class Program { static void Main() { Test test = new Test(); const int m = 1000000000; Stopwatch s1 = Stopwatch.StartNew(); // Version 1: access readonly. for (int i = 0; i < m; i++) { if (test.GetValue1() != 1) { throw new Exception(); } } s1.Stop(); Stopwatch s2 = Stopwatch.StartNew(); // Version 2: access field. for (int i = 0; i < m; i++) { if (test.GetValue2() != 1) { throw new Exception(); } } s2.Stop(); Stopwatch s3 = Stopwatch.StartNew(); // Version 3: access const. for (int i = 0; i < m; i++) { if (test.GetValue3() != 1) { throw new Exception(); } } s3.Stop(); // Results. Console.WriteLine(s1.ElapsedMilliseconds); Console.WriteLine(s2.ElapsedMilliseconds); Console.WriteLine(s3.ElapsedMilliseconds); } }
562 ms readonly 300 ms int 555 ms const
Const. Often it is better to use constants instead. If you have a value that was established outside of your program (such as by science or research) use const.
Also If your value is constant and you are in complete control of the program, const is better.
DLLs. When you use const, the C# compiler embeds the const variable's value directly in the IL code. Therefore, it essentially erases the const as a separate entity.
Warning If programs that depend on a const are not recompiled after the const value changes, they may break.
ReadOnlyCollection. When you make a field reference of a collection readonly, just that reference itself is readonly. The elements inside are no different.
Thus You cannot make a collection itself readonly with just the readonly keyword.
However You can use the ReadOnlyCollection type, which wraps other collections and prevents writes.
A summary. We considered a practical usage of the readonly keyword. Further we compared the performance of readonly and const in an object-oriented program.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Jul 4, 2021 (edit).
© 2007-2024 Sam Allen.