C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
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.NowTip: 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)
Compiler-generated code: C#
class Manager
{
readonly DateTime _startup = DateTime.Now;
public DateTime GetStartup()
{
return this._startup;
}
}
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)
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}
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
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
Also: If your value is constant and you are in complete control of the program, const is better.
Caution: If programs that depend on a const are not recompiled after the const value changes, they may break.
DllImport, DllexportThus: 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