Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

immutable value types

Tags:

c#

.net

clr

I am reading Eric Liperts' blog about Mutating Readonly Structs and I see many references here in SO to this blog as an argument why value types must be immutable. But still one thing is not clear, says that when you access value type you always get the copy of it and here is the example :

struct Mutable
{
    private int x;
    public int Mutate()
    {
        this.x = this.x + 1;
        return this.x;
    }
}

class Test
{
    public readonly Mutable m = new Mutable();
    static void Main(string[] args)
    {
        Test t = new Test();
        System.Console.WriteLine(t.m.Mutate());
        System.Console.WriteLine(t.m.Mutate());
        System.Console.WriteLine(t.m.Mutate());
    }
}

And the question is this why when I change the

public readonly Mutable m = new Mutable();

to

public Mutable m = new Mutable();

everything starts to work es expected.

Please can you explain more clear why Value Types must be immutable. I know that it is good for thread safety, but in this case same can be applied to reference types.

like image 889
NDeveloper Avatar asked Jul 04 '11 08:07

NDeveloper


2 Answers

Structs with mutating methods behave strangely in several situations.

The example you already discovered is a readonly field. A defensive copy is necessary because you don't want to mutate a readonly field.

But also when used as properties. Once again an implicit copy happens, and only the copy is mutated. Even if the property has a setter.

struct Mutable
{
    private int x;
    public int Mutate()
    {
        this.x = this.x + 1;
        return this.x;
    }
}

Mutable property{get;set;}

void Main()
{
    property=new Mutable();
    property.Mutate().Dump();//returns 1
    property.Mutate().Dump();//returns 1 :(
}

This shows that mutating methods are problematic on structs. But it doesn't show that a mutable struct with either public fields or properties that have a setter is problematic.

like image 188
CodesInChaos Avatar answered Sep 28 '22 07:09

CodesInChaos


The thread-safety is a clear technical reason. It applies to value types as well as to reference types (see System.String).

The more general guideline "value types should be immutable" is different. It is about readability of code, and comes mainly from the confusion that mutable values can cause. This code snippet is just one example. Most people would not expect the 1,1,1 outcome.

like image 33
Henk Holterman Avatar answered Sep 28 '22 05:09

Henk Holterman