What does immutable and readonly mean in C#? - c#

Is it correct that it is not possible to change the value of an immutable object?
I have two scenarios regarding readonly that I want to understand:
What if I have a collection and mark it as readonly, like the following. Can I still call _items.Add?
private readonly ICollection<MyItem> _items;
And also for the following variable, if later on I call _metadata.Change which will change the internal values of a couple member variable in the Metadata instance. Is _metadata still immutable?
private readonly Metadata _metadata;
For both variables above, I totally understand that I can't directly assign new values to them outside of initializer and constructors.

I suggest you to read the series of blog posts by Eric Lippert. The first part is Immutability in C# Part One: Kinds of Immutability. Very informative and helpful, as always. The series describes what does it mean for a variable to be readonly, immutable etc. in details.
Generally, readonly means only that you can't re-assign a field outside the constructor. The field itself can be modified as long as it stays the same instance. So yes, you can add elements to the collection stored in readonly field.
About mutability, this is more complex and it depends a bit what kind of mutability you consider. When Metadata internal values are references and those references itself (the instances it point to) doesn't change, you could say Metadata stays not mutated. But it is mutated logically. See Eric's posts for more insights.

Marking a field as read-only only means that you cannot change the value of that field. It has no bearing on the internal state of the object there. In your examples, while you would not be able to assign a new metadata object to the _metadata field, nor a new ICollection to the _items field (outside of a constructor that is), you can change the internal values of the existing objects stored in those fields.

An immutable object is one that cannot be changed, once created. In C# strings are immutable. If you look at the string manipulation routines you can see that all of them return a new, modified, string and leaves the original string unchanged.
This facilitates the string handling considerably. When you have a reference to a string, you can be sure that noone else will unexpectedly change it under your feet.
readonly is something else. It means that the reference cannot be changed, once set and that it can only be set during object construction. In your examples you can change the contents of _items or the properties of _metadata, but you cannot assign another ICollection<MyItem> to the _items member or another Metadata instance to _metadata.
readonly is set on the reference to an object. Immutability is a property of the object itself. These can be freely combined. To make sure that a property is not changed in any way, it should be a readonly reference to an immutable object.

There is nothing preventing you from mutating an object stored in a readonly field. So you CAN call _items.Add() and metadata._Change() outside the constructor/initializer. readonly only prevents you from assigning new values to those fields after construction.

private readonly ICollection<MyItem> _items;
Does not prevent items from being added. This simply prevents _items from being re-assigned. The same is true for _metadata. Accessible members of _metadata can be changed - _metadata cannot be re-assigned.

Yes.
Readonly doesn't equal to immutable. You can still call _metadata.Change.

The readonly keyword applies to a variable - this means you can't assign another value to it, but you can alter its internal state. That's why you can alter a collection's items but you can't assign a new collection to the variable.

In languages like C++ there are quite a few different uses of the keyword "const", it is partly easy for developers to pass constant parameters and also constant pointers of constant values.
That is not easy in C#.
We need to build immutable class by definition, which means Once an instance is created, there is no way it can be changed programmatically.
Java has a little easier way than C# because of the keyword final and its usages.
Lets consider this example and see how immutable it is..
public sealed class ImmutableFoo
{
private ImmutableFoo()
{
}
public string SomeValue { get; private set; }
//more properties go here
public sealed class Builder
{
private readonly ImmutableFoo _instanceFoo = new ImmutableFoo();
public Builder SetSomeValue(string someValue)
{
_instanceFoo.SomeValue = someValue;
return this;
}
/// Set more properties go here
///
public ImmutableFoo Build()
{
return _instanceFoo;
}
}
}
You can use it like this
public class Program
{
public static void Main(string[] args)
{
ImmutableFoo foo = new ImmutableFoo.Builder()
.SetSomeValue("Assil is my name")
.Build();
Console.WriteLine(foo.SomeValue);
Console.WriteLine("Hit enter to terminate");
Console.ReadLine();
}
}

Related

Compilation error. Using properties with struct

Please explain the following error on struct constructor. If i change struct to class
the erros are gone.
public struct DealImportRequest
{
public DealRequestBase DealReq { get; set; }
public int ImportRetryCounter { get; set; }
public DealImportRequest(DealRequestBase drb)
{
DealReq = drb;
ImportRetryCounter = 0;
}
}
error CS0188: The 'this' object cannot be used before all of its fields are assigned to
error CS0843: Backing field for automatically implemented property
'DealImportRequest.DealReq' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
As the error message recommends, you can resolve this by calling the default constructor from a constructor initializer.
public DealImportRequest(DealRequestBase drb) : this()
{
DealReq = drb;
ImportRetryCounter = 0;
}
From the language specification:
10.7.3 Automatically implemented properties
When a property is
specified as an automatically
implemented property, a hidden backing
field is automatically available for
the property, and the accessors are
implemented to read from and write to
that backing field. [...] Because the
backing field is inaccessible, it can
be read and written only through the
property accessors, even within the
containing type. [...] This
restriction also means that definite
assignment of struct types with
auto-implemented properties can only
be achieved using the standard
constructor of the struct, since
assigning to the property itself
requires the struct to be definitely
assigned. This means that user-defined
constructors must call the default
constructor.
The other (more verbose) alternative, of course, is to manually implement the properties and set the backing fields yourself in the constructor.
Do note that the struct you have there is mutable. This is not recommended. I suggest you either make the type a class (your compilation problems should go away immediately) or make the type immutable. The easiest way to accomplish this, assuming the code you have presented is the entire struct, would be to make the setters private (get; private set;). Of course, you should also make sure that you don't add any mutating methods to the struct afterwards that rely on private access to modify the fields. Alternatively, you could back the properties with readonly backing fields and get rid of the setters altogether.
The code you have is equivalent to the following code:
public struct DealImportRequest
{
private DealRequestBase _dr;
private int _irc;
public DealRequestBase DealReq
{
get { return _dr; }
set { _dr = value; }
}
public int ImportRetryCounter
{
get { return _irc; }
set { _irc = value; }
}
/* Note we aren't allowed to do this explicitly - this is didactic code only and isn't allowed for real*/
public DealImportRequest()
{
this._dr = default(DealRequestBase); // i.e. null or default depending on whether this is reference or value type.
this._irc = default(int); // i.e. 0
}
public DealImportRequest(DealRequestBase drb)
{
this.DealReq = drb;
this.ImportRetryCounter = 0;
}
}
Now, all I have done here is remove the syntactic sugar that:
Implements automatic properties.
Works out which members are dealt with relative to this.
Gives all structs a default no-parameter constructor.
The first two are optional (you could write them explicitly if you wished) but the third is not - we aren't allowed to write our own code for a struct's parameterless constructor, we have to go with one that works like the one in the code above being given to us automatically.
Now, looked at here, suddenly the meaning of the two errors becomes clear - your constructor is implicitly using this before it's fields are assigned (error 188) and those fields are those backing the automatic properties (error 843).
It's a combination of different automatic features that normally we don't have to think about, but in this case don't work well. We can fix this by following the advice in the error message for 843 and calling the default constructor as part of your explicit constructor:
public DealImportRequest(DealRequestBase drb)
:this()
{
DealReq = drb;
ImportRetryCounter = 0;
}
Considering this in relation to my expanded version of your code above, you can see how this solves the problem, because it calls the constructor that assigns to the backing fields before it proceeds.
I would recommend not using auto-properties with structures unless you have a good reason to use them. Wrapping a class field in a read-write property is useful because it makes it possible for an instance to control the circumstances where it may be read or written, and take action when a read or write takes place. Further, code within an object instance can identify the instance being acted upon, and may thus perform a special action only when reading and writing a particular instance. Using an auto-property in an early version of a class will make it possible for future versions of the class to use a manually-implemented property including the aforementioned benefits while retaining compatibility with already-compiled client code. Unfortunately, wrapping a struct field in a read-write property doesn't offer those same benefits because the fields of one struct instance can be copied to another without either instance having any say in the matter. If the semantics of a struct allow a property to be written with arbitrary values in most instances [as would be the case for an auto-property], then any legitimate replacement would be semantically equivalent to a field.

Are there any reasons to use private properties in C#?

I just realized that the C# property construct can also be used with a private access modifier:
private string Password { get; set; }
Although this is technically interesting, I can't imagine when I would use it since a private field involves even less ceremony:
private string _password;
and I can't imagine when I would ever need to be able to internally get but not set or set but not get a private field:
private string Password { get; }
or
private string Password { set; }
but perhaps there is a use case with nested / inherited classes or perhaps where a get/set might contain logic instead of just giving back the value of the property, although I would tend to keep properties strictly simple and let explicit methods do any logic, e.g. GetEncodedPassword().
Does anyone use private properties in C# for any reason or is it just one of those technically-possible-yet-rarely-used-in-actual-code constructs?
Addendum
Nice answers, reading through them I culled these uses for private properties:
when private fields need to be lazily loaded
when private fields need extra logic or are calculated values
since private fields can be difficult to debug
in order to "present a contract to yourself"
to internally convert/simplify an exposed property as part of serialization
wrapping global variables to be used inside your class
I use them if I need to cache a value and want to lazy load it.
private string _password;
private string Password
{
get
{
if (_password == null)
{
_password = CallExpensiveOperation();
}
return _password;
}
}
The primary usage of this in my code is lazy initialization, as others have mentioned.
Another reason for private properties over fields is that private properties are much, much easier to debug than private fields. I frequently want to know things like "this field is getting set unexpectedly; who is the first caller that sets this field?" and it is way easier if you can just put a breakpoint on the setter and hit go. You can put logging in there. You can put performance metrics in there. You can put in consistency checks that run in the debug build.
Basically, it comes down to : code is far more powerful than data. Any technique that lets me write the code I need is a good one. Fields don't let you write code in them, properties do.
perhaps there is a use case with nested / inherited classes or perhaps where a get/set might contain logic instead of just giving back the value of the property
I personally use this even when I don't need logic on the getter or setter of a property. Using a property, even a private one, does help future-proof your code so that you can add the logic to a getter later, if required.
If I feel that a property may eventually require extra logic, I will sometimes wrap it into a private property instead of using a field, just so I don't have to change my code later.
In a semi-related case (though different than your question), I very frequently use the private setters on public properties:
public string Password
{
get;
private set;
}
This gives you a public getter, but keeps the setter private.
One good usage for private get only properties are calculated values. Several times I've had properties which are private readonly and just do a calculation over other fields in my type. It's not worthy of a method and not interesting to other classes so private property it is.
Lazy initialization is one place where they can be neat, e.g.
private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);
private MyType MyType { get { return this.mytype.Value; } }
// In C#6, you replace the last line with: private MyType MyType => myType.Value;
Then you can write: this.MyType everywhere rather than this.mytype.Value and encapsulate the fact that it is lazily instantiated in a single place.
One thing that's a shame is that C# doesn't support scoping the backing field to the property (i.e. declaring it inside the property definition) to hide it completely and ensure that it can only ever be accessed via the property.
The only one usage that I can think of
private bool IsPasswordSet
{
get
{
return !String.IsNullOrEmpty(_password);
}
}
Properties and fields are not one to one. A property is about the interface of a class (whether talking about its public or internal interface), while a field is about the class's implementation. Properties should not be seen as a way to just expose fields, they should be seen as a way to expose the intent and purpose of the class.
Just like you use properties to present a contract to your consumers on what constitutes your class, you can also present a contract to yourself for very similar reasons. So yes, I do use private properties when it makes sense. Sometimes a private property can hide away implementation details like lazy loading, the fact that a property is really a conglomeration of several fields and aspects, or that a property needs to be virtually instantiated with each call (think DateTime.Now). There are definitely times when it makes sense to enforce this even on yourself in the backend of the class.
I use them in serialization, with things like DataContractSerializer or protobuf-net which support this usage (XmlSerializer doesn't). It is useful if you need to simplify an object as part of serialization:
public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
get { return SomeProp.ToInt32(); }
set { SomeProp = SomeComplexType.FromInt32(value); }
}
I use private properties to reduce code for accessing sub properties which often to use.
private double MonitorResolution
{
get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
}
It is useful if there are many sub properties.
One thing I do all the time is store "global" variables/cache into HttpContext.Current
private static string SomeValue{
get{
if(HttpContext.Current.Items["MyClass:SomeValue"]==null){
HttpContext.Current.Items["MyClass:SomeValue"]="";
}
return HttpContext.Current.Items["MyClass:SomeValue"];
}
set{
HttpContext.Current.Items["MyClass:SomeValue"]=value;
}
}
I use them every now and then. They can make it easier to debug things when you can easily put in a breakpoint in the property or you can add a logging statement etc.
Can be also be useful if you later need to change the type of your data in some way or if you need to use reflection.
I know this question is very old but the information below was not in any of the current answers.
I can't imagine when I would ever need to be able to internally get but not set
If you are injecting your dependencies you may well want to have a Getter on a Property and not a setter as this would denote a readonly Property. In other words the Property can only be set in the constructor and cannot be changed by any other code within the class.
Also Visual Studio Professional will give information about a Property and not a field making it easier to see what your field is being used.
It is a common practice to only modify members with get/set methods, even private ones. Now, the logic behind this is so you know your get/set always behave in a particular way (for instance, firing off events) which doesn't seem to make sense since those won't be included in the property scheme... but old habits die hard.
It makes perfect sense when there is logic associated with the property set or get (think lazy initialization) and the property is used in a few places in the class.
If it's just a straight backing field? Nothing comes to mind as a good reason.
Well, as no one mentioned you can use it to validate data or to lock variables.
Validation
string _password;
string Password
{
get { return _password; }
set
{
// Validation logic.
if (value.Length < 8)
{
throw new Exception("Password too short!");
}
_password = value;
}
}
Locking
object _lock = new object();
object _lockedReference;
object LockedReference
{
get
{
lock (_lock)
{
return _lockedReference;
}
}
set
{
lock (_lock)
{
_lockedReference = value;
}
}
}
Note: When locking a reference you do not lock access to members of the referenced object.
Lazy reference: When lazy loading you may end up needing to do it async for which nowadays there is AsyncLazy. If you are on older versions than of the Visual Studio SDK 2015 or not using it you can also use AsyncEx's AsyncLazy.
One more usage would be to do some extra operations when setting value.
It happens in WPF in my case, when I display some info based on private object (which doesn't implement INotifyPropertyChanged):
private MyAggregateClass _mac;
private MyAggregateClass Mac
{
get => _mac;
set
{
if(value == _mac) return;
_mac = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DisplayInfo)));
}
}
public string DisplayInfo => _mac.SomeStringInformationToDisplayOnUI;
One could also have some private method, such as
private void SetMac(MyAggregateClass newValue)
to do that.
Some more exotic uses of explicit fields include:
you need to use ref or out with the value - perhaps because it is an Interlocked counter
it is intended to represent fundamental layout for example on a struct with explicit layout (perhaps to map to a C++ dump, or unsafe code)
historically the type has been used with BinaryFormatter with automatic field handling (changing to auto-props changes the names and thus breaks the serializer)
Various answers have mentioned using properties to implement a lazy member. And this answer discussed using properties to make live aliases. I just wanted to point out that those two concepts sometimes go together.
When using a property to make an alias of another object's public property, the laziness of that property is preserved:
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IDbConnection Conn => foo.bar.LazyDbConnection;
On the other hand, retrieving that property in the constructor would negate the lazy aspect:
Conn = foo.bar.LazyDbConnection;
Looking into the guideline (Properties (C# Programming Guide)) it seems no one expects to use properties as private members.
Properties enable a class to expose a public way of getting and setting values, while hiding implementation or verification code.
In any case it can be interchanged by one or two methods and vice versa.
So the reason can be to spare parentheses on getting and get field syntax on setting.

Doesn't this defeat the whole purpose of having read-only properties?

I know how to use properties and I understand that they implicitly call underlying get and set accessors, depending on whether we are writing to or reading from a property.
static void Main(string[] args)
{
A a = new A();
(a.b).i = 100;
}
class A
{
private B _b = new B();
public B b
{
get { return _b; }
}
}
class B
{
public int i;
}
What code (a.b).i = 100; essentially does is that first property’s get accessor returns a reference to an object _b, and once we have this reference, we are able to access _b’s members and change their values.
Thus, in our example, having read only property only prevents outside code from changing the value of a reference variable _b, but it doesn’t prevent outside code from accessing _b’s members.
So it seems that property can only detect whether we are trying to read from or write to a variable ( in our case variable _b ) located on the stack, while it’s not able to detect whether we’re trying to also write to members of an object to which the variable on the stack ( assuming this variable is of reference type ) points to.
a) But doesn’t that defeat the whole purpose of having read-only properties? Wouldn’t it be more effective if properties had the ability to also detect whether we’re trying to access members of an object returned by get accessor( assuming backing field is of a reference type )?
thank you
Immutability is not transitive; you can't expect mutable objects into an immutable accessor to be immutable.
Your reference is read only, not your object.
Imagine a class like this:
public class A
{
private List<int> _myList<int> = new List<int>();
public List<int> MyList { get { return _myList; } }
}
Now, users of the class can add and remove and access items in the list, but they cannot replace the list itself. This is important. It allows you to do things inside the class like assume the _myList member is never null, for example.
Put a more general way, this paradigm allows you do define an interface into your class such that users can use the types in the properties you expose, but they cannot just swap instances of complex types out from under you.
No, it does not defeat the purpose of read-only properties.
It is possible to use read-only properties that don't let the user change the underlying data. For example, you can have your property return a System.Collections.ObjectModel.ReadOnlyCollection even though the underlying type is a List. This, of course, won't prevent the user from changing the properties of the items in the collection.
Of course you can access B.i; it's public. You're thinking that since _b is private, all methods should be private when fetched through A? In that case it's pretty useless as you wouldn't be able to use B for anything.
You ask:
Doesn’t that defeat the whole purpose
of having read-only properties?
But look: your B.i member is a public field.
I ask you, then: what is the purpose of having a public field? It only makes sense if you want users of your code to be able to change that field's value. If you don't want that, it should be a private field, or (if you want to provide read but not write access) a property with a private set accessor.
So there's your answer. private B _b serves its purpose in the code you posted quite well (_b cannot be externally set to something new), just as public int i serves its purpose equally well (i can be externally changed).
Reference immutability is a popular feature request. Too bad its is so dramatically non CLS compliant. Very few languages have this notion, I only know of C++ (but don't get out much).
The key problem that this needs to be enforced by the CLR. C++ doesn't need to enforce this at runtime, only a C++ compiler is required to ensure that const contracts are observed. It has no support at all for language interop, beyond a bolt-on like COM.
This won't fly in .NET, there's little point in declaring a reference immutable and have that verified by the compiler when another language can stomp all over it because it doesn't have the syntax to express immutability. I reckon we'll get it some day, not Real Soon.
As a minor point, you don't have to write (a.b).i = 100; but simply
a.b.i = 100;
Back to your question, I don't think it defeats the purpose. You can still not do the following:
a.b = new B();
because there's no public set(). If you want the member i of class B to be read only, you can do the same thing as you did to member _b of class A by making it private and providing a public get(), but not set(). Off the top my head, doing what you propose might lead to many unexpected consistencies (I'm sure the language designers did not overlook this).
Entirely dependent on the situation, but read only access to a mutable object is a commonly used design. In many cases you simply want to ensure that the object itself remains the same.
Some classes (like String object in Java, and I believe in C# as well) are entirely immutable, where as others are only partially mutable. Consider an ActiveRecord style of object for which most fields are mutable, but the ID is immutable. If your class holds an ActiveRecord in a read only property, external classes cannot swap it for a different ActiveRecord object and thus change the ID, which might break assumptions within your class.
I disagree. Your property is for the class B, not for the members of class B. This means you can't assign a new Object to b. It doesn't mean that B's public members suddenly become private.
readonly applies to the class property, not the object that the property refers to. It keeps you from being able to write a.b = new B();, and that is all it does. It places no constraints on what you can do to the object once you get a reference to it. I think what you are discovering is that readonly make the most sense when applied to value types or immutable class types.
Another use case:
interface INamedPerson
{
String Name { get; }
}
class Bob : INamedPerson
{
public String Name { get; set; }
}
class Office
{
// initialisation code....
public INamedPerson TheBoss { get; }
public IEnumerable<INamedPerson> Minions { get; }
}
Now, if you have an instance of the Office, as long as you don't go cheating with casts, you have read-only access to everyone's names, but can't change any of them.
Ah. Encapsulation does the instantiated class inherit the containing class's access level. Exposing type B as a public property of type A. 'B.i' is public so it should be accessible from outside the same way 'A.b' is public.
A.b returns a reference of a privately accessible type B, however type B has a publicly accessible field i. My understanding is that you can set the i field of B but you can't set the b property of A externally. The B type property of A is readonly however the reference to type B does not define the same readonly access to its fields.
I'm sure you can modify the definition of type B to suit your need for the access level of B's fields or properties.

Immutable type and property in C#

What is meant by immutable type and immutable property in C# ? can you give simple example?
An immutable type is a type of which its properties can only be set at initialization. Once an object is created, nothing can be changed anymore. An immutable property is simply a read-only property.
In the following example, ImmutableType is an immutable type with one property Test. Test is a read-only property. It can only be set at construction.
class ImmutableType
{
private readonly string _test;
public string Test
{
get { return _test; }
}
public ImmutableType(string test)
{
_test = test;
}
}
See also: The Wikipedia article, and some Stack Overflow questions on the topic.
In addition to #fretje's answer above, in C#6 and later, getter-only auto properties have now been implemented, which allows for immutable auto-properties without the need for the additional explicit private readonly backing field. The equivalent code would be abbreviated to:
class ImmutableType
{
public string Test
{
get; // No Set at all, not even a private set.
}
public ImmutableType(string test)
{
Test = test; // The compiler understands this and initializes the backing field
}
}
Note that private set only provides a restricted encapsulation of change to the property from within the same class, and thus isn't truly immutable:
public string Test
{
get;
private set; // Not immutable, since this is still mutable from within the class
}
More about immutability
As others have said, an immutable Property is a property which cannot change once it has been set. Setting of the 'only' value is done during construction.
An immutable Type is a type where all (externally visible) properties and fields are immutable - for example the "Record" Type originally scheduled for C#7 (hopefully now 8) would have been an immutable type. Other examples of Immutable Types are Tuples, and all anonymous classes.
Immutable fields should be qualified with the readonly keyword in C# - this is enforced by the compiler to ensure that no other code attempts to change the field outside of the constructor.
Wherever possible, immutability of fields, variables and properties is regarded as good practice, as this greatly reduces the surface area for bugs (since fields represent the state of an object, preventing change to fields reduces the number of states).
The benefit of immutability is especially important in multi-threaded programs, where two or more threads concurrently access the same object. Since multiple concurrent reading threads can safely read the value of a field or property, the programmer doesn't need to be concerned about thread safety issues relating to change to the field by other threads (because change to the property is prohibited)
One common drawback of immutability when dealing with complex objects consisting of multiple composed objects, is that the entire graph needs to be built 'in one go', which can lead to messy code. A common solution here is to use the Builder pattern as a scaffold, which allows a transient, mutable representation to be built in steps, and then the final, immutable object is obtained in the final .Build() step.
fretje is correct. The most popular example of an immutable type is a string object in C#. This is the entire reason that StringBuilder exists.
There is no clear definition for immutability in C#:
It usually entails all public fields to be readonly and all public properties to have init setter or no setter.
It may also extend this to private members (although it is common to use mutable private members to cache values ie the hashcode)
It may also mean all members are themselves of immutable types. As otherwise a consumer can still modify the object by calling a member method
It may also mean all methods always return the same output when called with the same arguments. In particular an immutable GetHashCode() means the object is safe to use as a key in dictionaries etc
A stronger and often more useful concept is that of - 'Data' an Immutable type which also has value semantics (usually by inheriting from IEquatable<T>)
Here is an example of a 'Data' type that satisfies all of the demands above:
record MyData(int age, DateTime JoinDate);
(see project F for more on how Data types are useful)

What are the benefits to marking a field as `readonly` in C#?

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?
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.
Robert Pickering has written a good blog post about the benefits of immutability. The post can be found here or at the archive.org backup.
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).
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).
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.
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.
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.
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/
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
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.
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.
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.
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.
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 ;
}
}
}
There can be a performance benefit in WPF, as it removes the need for expensive DependencyProperties. This can be especially useful with collections

Categories

Resources