332

What are the benefits of having a member variable declared as read only? Is it just protecting against someone changing its value during the lifecycle of the class or does using this keyword result in any speed or efficiency improvements?

Robert Columbia
  • 6,012
  • 14
  • 28
  • 36
leora
  • 163,579
  • 332
  • 834
  • 1,328
  • 9
    Good external answer: http://www.dotnetperls.com/readonly – OneWorld Feb 28 '12 at 19:48
  • 3
    Interesting. This is essentially the C# equivalent of this Java question http://stackoverflow.com/questions/137868/using-final-modifier-whenever-applicable-in-java Discussion here is much less heated though... hmm... – RAY Apr 24 '12 at 09:28
  • 7
    It may be worth noting that `readonly` fields of structure types impose a performance penalty compared with mutable fields that are simply not mutated, since the invocation of any member of a `readonly` value-type field will cause the compiler to make a copy of the field and invoke the member on that. – supercat Oct 28 '12 at 01:22
  • 2
    more on the performance penalty: http://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/ – CAD bloke Jan 15 '16 at 02:03

14 Answers14

202

I don't believe there are any performance gains from using a readonly field. It's simply a check to ensure that once the object is fully constructed, that field cannot be pointed to a new value.

However "readonly" is very different from other types of read-only semantics because it's enforced at runtime by the CLR. The readonly keyword compiles down to .initonly which is verifiable by the CLR.

The real advantage of this keyword is to generate immutable data structures. Immutable data structures by definition cannot be changed once constructed. This makes it very easy to reason about the behavior of a structure at runtime. For instance, there is no danger of passing an immutable structure to another random portion of code. They can't changed it ever so you can program reliably against that structure.

Here is a good entry about one of the benefits of immutability: Threading

JYelton
  • 32,870
  • 25
  • 119
  • 184
JaredPar
  • 673,544
  • 139
  • 1,186
  • 1,421
  • 6
    If you read this, http://stackoverflow.com/questions/9860595/prevent-changing-the-value-of-string-empty read only member can be modified and looks like an inconsistent behavioir by .net – Akash Kava Mar 26 '12 at 08:13
  • 1
    Can you please update the link to the post on Threading above? It's broken. – Akshay Khot Jun 20 '20 at 00:33
196

The readonly keyword is used to declare a member variable a constant, but allows the value to be calculated at runtime. This differs from a constant declared with the const modifier, which must have its value set at compile time. Using readonly you can set the value of the field either in the declaration, or in the constructor of the object that the field is a member of.

Also use it if you don't want to have to recompile external DLLs that reference the constant (since it gets replaced at compile time).

Yuri Ghensev
  • 2,292
  • 4
  • 27
  • 44
Bill the Lizard
  • 369,957
  • 201
  • 546
  • 842
  • 5
    but how about the benefits of speed and efficiency? are there any? – Artemious Oct 21 '20 at 09:32
  • It pays to bare in mind that if you assign readonly to something like a class such as `private readonly TaskCompletionSource _ready = new TaskCompletionSource();` then you can still use `_ready.SetResult(true)` so the readonly applies only to the field and not necessarily the object's properties or state. Const is also not just as simple as "compile time" - it can't be used for all the same things like readonly can... const can only hold strings, ints bools or null. For example you can't do `const HttpClient hello5 = new HttpClient();` but you can for `readonly` – NotoriousPyro Mar 04 '21 at 23:42
  • @NotoriousPyro the reason you can't do `const HttpClient hello5 = new HttpClient()` is precisely because a new HttpClient is allocated at runtime. It really is as simple as "compile-time". Even structs are allocated at runtime and cannot be const. – Leonardo G Apr 21 '21 at 11:49
75

There are no apparent performance benefits to using readonly, at least none that I've ever seen mentioned anywhere. It's just for doing exactly as you suggest, for preventing modification once it has been initialised.

So it's beneficial in that it helps you write more robust, more readable code. The real benefit of things like this come when you're working in a team or for maintenance. Declaring something as readonly is akin to putting a contract for that variable's usage in the code. Think of it as adding documentation in the same way as other keywords like internal or private, you're saying "this variable should not be modified after initialisation", and moreover you're enforcing it.

So if you create a class and mark some member variables readonly by design, then you prevent yourself or another team member making a mistake later on when they're expanding upon or modifying your class. In my opinion, that's a benefit worth having (at the small expense of extra language complexity as doofledorfer mentions in the comments).

Xiaofu
  • 14,396
  • 2
  • 30
  • 45
  • And otoh desimplifies the language. Not denying your benefit statement, however. – dkretz Nov 10 '08 at 05:37
  • 3
    I agree, but I suppose the real benefit comes when more than one person is working on the code. It's like having a small design statement within the code, a contract for its usage. I should probably put that in the answer, hehe. – Xiaofu Nov 11 '08 at 03:33
  • 8
    This answer and discussion is actually the best answer in my opinion +1 – Jeff Martin Jan 29 '09 at 17:55
  • @Xiaofu: You made me constant of the idea of readonly hahaha beautiful explanation that nobody in this world could explain the silliest mind an understand – Jasmine Mar 20 '15 at 11:54
  • Ie you are staying intent in your code that this value should not change at any time. – Andez Apr 28 '20 at 16:00
53

To put it in very practical terms:

If you use a const in dll A and dll B references that const, the value of that const will be compiled into dll B. If you redeploy dll A with a new value for that const, dll B will still be using the original value.

If you use a readonly in dll A and dll B references that readonly, that readonly will always be looked up at runtime. This means if you redeploy dll A with a new value for that readonly, dll B will use that new value.

Daniel Auger
  • 12,072
  • 5
  • 46
  • 71
  • 5
    This is a good practical example to understand the difference. Thanks. – Shyju May 03 '16 at 20:54
  • On the other hand, `const` may have performance gain over `readonly`. Here is a bit deeper explanation with code : https://www.dotnetperls.com/readonly – Dio Phung Oct 14 '16 at 23:33
  • 2
    I think the biggest practical term is missing from this answer: the ability to store values computed at runtime into `readonly` fields. You can’t store a `new object();` in a `const` and that makes sense because you can’t bake non-value things such as references into other assemblies during compile time without changing identity. – binki Jun 22 '18 at 19:09
16

There is a potential case where the compiler can make a performance optimization based on the presence of the readonly keyword.

This only applies if the read-only field is also marked as static. In that case, the JIT compiler can assume that this static field will never change. The JIT compiler can take this into account when compiling the methods of the class.

A typical example: your class could have a static read-only IsDebugLoggingEnabled field that is initialized in the constructor (e.g. based on a configuration file). Once the actual methods are JIT-compiled, the compiler may omit whole parts of the code when debug logging is not enabled.

I have not checked if this optimization is actually implemented in the current version of the JIT compiler, so this is just speculation.

Aman Chourasiya
  • 523
  • 4
  • 14
  • is there a source for this? – Sedat Kapanoglu Sep 03 '16 at 01:30
  • 5
    The current JIT compiler in fact does implement this, and has since CLR 3.5. https://github.com/dotnet/coreclr/issues/1079 – mirhagk Oct 17 '16 at 19:41
  • No optimizations can be done on readonly fields for the simple reason that readonly fields are not readonly but readwrite. They are just a compiler hint that most compilers respect and the values of readonly fields can easily be overwritten through reflection (although not in partially trusted code). – Christoph May 19 '19 at 17:42
11

Keep in mind that readonly only applies to the value itself, so if you're using a reference type readonly only protects the reference from being change. The state of the instance is not protected by readonly.

Brian Rasmussen
  • 109,816
  • 33
  • 208
  • 305
3

Don't forget there is a workaround to get the readonly fields set outside of any constructors using out params.

A little messy but:

private readonly int _someNumber;
private readonly string _someText;

public MyClass(int someNumber) : this(data, null)
{ }

public MyClass(int someNumber, string someText)
{
    Initialise(out _someNumber, someNumber, out _someText, someText);
}

private void Initialise(out int _someNumber, int someNumber, out string _someText, string someText)
{
    //some logic
}

Further discussion here: http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx

ViRuSTriNiTy
  • 4,581
  • 1
  • 27
  • 52
Adam Naylor
  • 5,745
  • 9
  • 46
  • 65
  • 6
    The fields are still assigned in the constructor.. there is no "getting around" that. It doesn't matter if the values are from single expressions, from a decomposed complex type, or assigned via call by reference semantics of `out` .. – user2864740 Oct 12 '17 at 23:07
  • 2
    This doesn't even attempt to answer the question. – Sheridan Jan 20 '20 at 18:18
3

Surprisingly, readonly can actually result in slower code, as Jon Skeet found when testing his Noda Time library. In this case, a test that ran in 20 seconds took only 4 seconds after removing readonly.

https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
Neil
  • 6,747
  • 4
  • 40
  • 42
  • 3
    Note that if the field is of a type which is a `readonly struct` in C# 7.2, the benefit of making the field non-readonly goes away. – Jon Skeet Jun 17 '18 at 16:58
0

Be careful with private readonly arrays. If these are exposed a client as an object (you might do this for COM interop as I did) the client can manipulate array values. Use the Clone() method when returning an array as an object.

Michael
  • 27
  • 3
  • 20
    No; expose a `ReadOnlyCollection` instead of an array. – SLaks Apr 17 '11 at 19:14
  • This should be a comment not a answer as it provides no answer to the question... – Peter Jun 16 '15 at 19:01
  • Funnily enough, I got told to put this sort of thing as an answer, rather than a comment when I did it on another post last week. – Kyle Baran Nov 15 '15 at 10:08
  • As of 2013, you can use `ImmutableArray`, which avoids boxing to an interface (`IReadOnlyList`) or wrapping in a class (`ReadOnlyCollection`). It has performance comparable to native arrays: https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/ – Charles Taylor Mar 06 '18 at 14:08
0

Another interesting part of usage of readonly marking can be protecting field from initialization in singleton.

for example in code from csharpindepth:

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
}

readonly plays small role of protecting field Singleton from being initialized twice. Another detail is that for mentioned scenario you can't use const because const forces creation during compile time, but singleton makes creation at run time.

Yuriy Zaletskyy
  • 4,587
  • 3
  • 31
  • 46
0

If you have a pre defined or pre calculated value that needs to remain same through out the program then you should use constant but if you have a value that needs to be provided at the runtime but once assigned should remain same throughout the program u should use readonly. for example if you have to assign the program start time or you have to store a user provided value at the object initialization and you have to restrict it from further changes you should use readonly.

waqar ahmed
  • 325
  • 2
  • 6
0

readonly can be initialized at declaration or get its value from the constructor only. Unlike const it has to be initialized and declare at the same time. readonly has everything const has, plus constructor initialization

code https://repl.it/HvRU/1

using System;

class MainClass {
    public static void Main (string[] args) {

        Console.WriteLine(new Test().c);
        Console.WriteLine(new Test("Constructor").c);
        Console.WriteLine(new Test().ChangeC()); //Error A readonly field 
        // `MainClass.Test.c' cannot be assigned to (except in a constructor or a 
        // variable initializer)
    }


    public class Test {
        public readonly string c = "Hello World";
        public Test() {

        }

        public Test(string val) {
          c = val;
        }

        public string ChangeC() {
            c = "Method";
            return c ;
        }
    }
}
mayo
  • 3,314
  • 1
  • 32
  • 40
Mina Gabriel
  • 17,138
  • 23
  • 89
  • 118
0

Adding a basic aspect to answer this question:

Properties can be expressed as readonly by leaving out the set operator. So in most cases you will not need to add the readonly keyword to properties:

public int Foo { get; }  // a readonly property

In contrast to that: Fields need the readonly keyword to achieve a similar effect:

public readonly int Foo; // a readonly field

So, one benefit of marking a field as readonly can be to achieve a similar write protection level as a property without set operator - without having to change the field to a property, if for any reason, that is desired.

code14214
  • 35
  • 5
-1

There can be a performance benefit in WPF, as it removes the need for expensive DependencyProperties. This can be especially useful with collections

Shane
  • 615
  • 1
  • 5
  • 21
  • `DependecyProperty` is used for a very different purpose than a field – Artemious Oct 21 '20 at 09:47
  • Agreed, and together they are in the same ecosystem of monitoring mutations. If you can gaurentee that a field does not change, then you don't need to monitor it's mutations, hence the performance benefit – Shane Oct 21 '20 at 11:06