Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is better between a readonly modifier and a private setter?

I've been working on creating a class and suddenly a thought came to my mind of what is the difference between the two codes:

public readonly string ProductLocation; 

AND

public string ProductLocation {      get;      private set; } 

Can you guys give me idea when to use the following better. thanks.

like image 329
Allan Chua Avatar asked Nov 02 '11 03:11

Allan Chua


People also ask

When should you use a read-only field?

In a field declaration, readonly indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class. A readonly field can be assigned and reassigned multiple times within the field declaration and constructor.

What is the purpose of readonly modifier?

Readonly Fields: In C#, you are allowed to declare a field using readonly modifier. It indicates that the assignment to the fields is only the part of the declaration or in a constructor to the same class.

What is the purpose of read-only variables?

Read-only variables can be used to gather information about the current template, the user who is currently logged in, or other current settings. These variables are read-only and cannot be assigned a value.

What is a private setter?

private setters are same as read-only fields. They can only be set in constructor. If you try to set from outside you get compile time error. public class MyClass { public MyClass() { // Set the private property.


2 Answers

The first one is a read-only field, while the second one gets compiled as a pair of methods (and all reads of the property ProductLocation gets compiled into calls to the corresponding get method and writes to it gets compiled into calls to the set method; internally, these methods will read from / write to an internal, automatically generated, non-read-only field). I'd say the most important difference is thread-safety! (how? read on!)

The basic usage of the class will look exactly the same: code in other classes will only be able to read the value, not change it. Also, the code to read the value will look exactly the same (for example, print(myInstace.ProductLocation); here, you cannot tell how it has been declared, cool, eh?)

The first, most trivial difference is that the property with private setter allows for instances of the same class to modify the value, while in the case of the readonly property, not even the object itself will be able to change the value.

Now, for the thread-safety. The readonly attribute on the field will change its memory visibility semantics when you are working with multiple threads (just like Java's final fields).

A readonly field can only be assigned to at declaration or in the constructor. The value assigned to a readonly field cannot be changed (at least not in a normal way) and it is guaranteed that every thread will see the correctly, initialized value after the constructor returns. Therefore, a readonly field is inherently thread-safe.

To achieve the same thread-safety with the property, you'd have to add some synchronization on your code, which is error-prone. It might lead to dead-locks, data races or reduced performance, depending on the case, and especially if you are not experienced.

So, if the value represents something that semantically cannot be changed after the object's construction, you should not declare a private setter (this would imply that the object might change it). Go for the readonly field (and maybe declare it private and declare a public property with only a getter accessing the field! This is actually the preferred form, since it is not good to expose fields, it is better to only expose methods -- there are many reasons explaining why in this answer)

like image 76
Bruno Reis Avatar answered Oct 05 '22 08:10

Bruno Reis


With C# 6.0 auto-property initializer there is less boilerplate way of doing

private readonly string productLocation;  public string ProductLocation { get { return productLocation; } }  

Which is

public string ProductLocation { get; }  

This is readonly. Only initialized from constructor or inline. It cannot be edited after initialization. (Immutable from anywhere)

However, if you use private set;

public string ProductLocation { get; private set }  

This is readonly from outside. But can be initialized anytime anywhere within the class itself. And can be edited within its life cycle by the class itself. (Mutable from class, immutable from outside)

like image 26
stratovarius Avatar answered Oct 05 '22 07:10

stratovarius