HomeSearch

C# readonly Keyword

Use the readonly keyword. Readonly prevents changes to fields after initialization.
Readonly. This keyword prevents a class field from being changed. Readonly fields can be initialized at runtime, unlike const values. Attempts to change them later are disallowed.constClass
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.

Manager: In the constructor, the startup time is initialized. We can assign the readonly field here.

ConstructorDateTime.Now

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.

C# program that uses readonly 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; } } Output (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.IL Disassembler
Compiler-generated code: C# 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.

Error: A readonly field cannot be assigned to (except in a constructor or a variable initializer).

C# program that causes error class Program { static readonly int _code = 100; static void Main() { _code = 200; } } Output 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.

C# program that uses public static readonly fields 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(); } } Output {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.

Error 1: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer) Error 2: 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).Benchmark

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.

Version 3: 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.

C# program that times readonly field 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); } } Output 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.

Caution: If programs that depend on a const are not recompiled after the const value changes, they may break.

DllImport, Dllexport
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.

ReadOnlyCollection
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.
Home
Dot Net Perls
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.