Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where are the readonly/const in .NET?

People also ask

What is readonly const in C#?

readonly keyword is used to define a variable which can be assigned once after declaration either during declaration or in constructor. const keyword is used to define a constant to be used in the program. Following is the valid usage of a readonly and const keywords in C#.

Can readonly be changed in C#?

Use the readonly keyword in C#You cannot change the value or reassign a value to a readonly variable or object in any other method except the constructor.

Why would you use readonly vs const in C#?

A const is a compile-time constant whereas readonly allows a value to be calculated at run-time and set in the constructor or field initializer. So, a 'const' is always constant but 'readonly' is read-only once it is assigned.


Immutability is still an area where C# is maturing. So far, C# has not adopted the const semantics of C++ ... which I actually think is a good thing. The behavior of const in C++ often made it challenging to design class hierarchies that worked they way you wanted. It wasn't uncommon to see code peppered with const_cast<> to bypass constness where it wasn't desirable. Hopefully, the designers of C# will invent a simpler but still expressive alternative.

At present, there is no language feature that marks parameters or objects passed to methods as immutable. The best you can do is pass an an object using an interface (or better yet a wrapper) that only permits read operations.

For some of the standard collection in .NET you can use the ReadOnlyCollection wrapper, which encapsulated any mutable ICollection type within a read-only container.

Creating immutable types requires planning and awareness of the language features. For example, the readonly keyword is your friend. It allows you to declare members of a class or struct as immutable. Unfortunately, this immutability only applies to the reference, not the members of the referenced object. What this means is that you can declare:

private readonly int[] m_Values = new int[100];

public void SomeMethod()
{
    m_Values = new int[50]; // illegal, won't compile!
    m_Values[10] = 42;      // perfectly legal, yet undesirable
}

In the above example, the reference to the array is immutable, but the individual elements of the array are not. This behavior extends beyond arrays, of course.

A practice I've found helpful when designing immutable types, is to separate the immutable behavior into its own interface which is then implemented by a class that manages the data. The interface only exposes get properties and methods that are guaranteed not to mutate the state of the object. It is then possible to pass instances of your type to methods as parameters of that interface type. This is a weak form of immutability support - since the called method can often cast the reference to the mutable type. A better, but more cumbersome alternative, is to create a wrapper implementation that implements that same interface and maintains a reference to the actual instance (much like ReadOnlyCollection does). This is more work but provides a stronger guarantee for immutability.

The approach you choose to use depends on how important guarantees of immutability are, and how much time and effort you are willing to spend to get there.

If you're interested in reading more on this topic, Eric Lippert has an excellent series of articles on immutability in C#.


There is no const modifier for method parameters in C#. If you want to have something similar to const guarantees you can use immutable types in your interfaces. For example, a method can accept an IEnumerable<T> instead of a mutable collection type. You can also look at ReadOnlyCollection.


I have notice a nice amount of parameters using struct.

One thing worth mentioning here is that C# exaggerates the difference between struct and class as compared to C++, by exaggerating the difference between value types and reference types. In C#, all classes are reference types, and all structs are value types. In .Net, everything is passed by value by default.

The result of this distinction for value types is that all value types are copied when passed to a function. If you pass a struct to a function, you are guaranteed that function will not change your original struct because the function is only working with a copy. Adding const to such a parameter is silly.

Reference types are passed by value, too. Or, more specifically, the reference itself is passed by value. So you have a copy of the reference, but it points to (refers to) the same object. Thus, changes made to the object by the function will persist after the function exits.

On surface, adding a const option, at least for reference types, seems like a good idea. Where it gets a little murky is with side effects. Or, rather, how is this enforced? Obviously it's easy enough to say that your code can't use property setters. But what about other methods? Any method call might need to change the object. Even property getters might have a side effect that changes something (say you implement a security feature to note when something was last accessed). Are you going to deny read access to a property because of the side effect?


The problem is that const correctness as used in C/C++ is only enforced by the compiler. And readily bypassed btw. The CLR actually enforces type safety in managed code, not the compiler. Necessarily so because the .NET framework supports many languages. The type system and interaction rules are laid out in the CLI, a common language infrastructure that needs to serve many goals and masters.

Const correctness is rare in current languages. Personally, I know of only C++, a language that is not ported to the CLI. Enforcing rules on languages that have nowhere near the syntax for them is difficult. Something as simple as unsigned integral types not being in the CLS left a notable mark on the design of the base assemblies.

Immutability (real, not faked with a compiler) keeps the MSFT teams thinking. It is popular, I know the C# team has been thinking about it. Good for concurrency, etcetera. Eric Lippert did a 11 part blog post series on it, kinda petered out though. Too big for one guy and his audience. If there will be a real move to getting it implemented, I trust them to think it through and make it work. Some day. Some language.