This C# keyword prevents a class
field from being changed. Readonly fields are initialized at runtime. Readonly does not affect individual elements in a field like a List
.
This C# modifier does not affect performance. It just enforces certain constraints in the compiler. This leads to greater program quality—but types like ImmutableList
are still needed.
Here we use the readonly
keyword to initialize a DateTime
struct
. We cannot set a const
DateTime
—this raises a compilation error.
DateTime
field as unavailable for further changes.readonly
field here.readonly
field.using System; class Program { static void Main() { Manager manager = new Manager(); Console.WriteLine(manager.GetStartup()); } } class Manager { readonly DateTime _startup; public Manager() { // Initialize startup time. this._startup = DateTime.Now; } public DateTime GetStartup() { // We cannot modify the DateTime here. return this._startup; } }9/26/2024 8:07:44 AM
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; } }
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.
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)
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.
static
readonly
fields when we cannot use a const
field or when the field may change.const
values are faster—they are inserted directly into the locations where used.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}
static
readonly
We can get an error from using public static
readonly
(or const
) fields. Here are some errors that can be encountered.
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
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).
readonly
field from the class
many times in a loop.int
field that is not readonly
many times in a tight loop.const
value in the loop. So no field needs to be accessed in this version.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
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
.
const
is better.We considered a practical usage of the readonly
keyword. Further we compared the performance of readonly
and const
in an object-oriented program.