This project is read-only.

Proposal for immutable type classes

Topics: C# Language Design
Apr 5, 2014 at 7:57 PM
Edited Apr 12, 2014 at 3:47 PM
It seems to me that a few legacy problems are nullable object references and mutable objects, I would like to propose a 3rd classification method (alongside struct and class) which is immutable by default, public by default, and can only be assigned to a 'variable' using 'let'. It borrows heavily from F#'s record-type.

type Vector
    float X;
    float Y;
    float Z;

    float Length = Math.Sqrt(X*X + Y*Y + Z*Z);

    Vector Add( Vector value ) => new Vector { X + value.X,Y + value.Y,Z + value.Z };

let value = new Vector( X=1, Y=2, X=3 );

//// * Can't modify an immutable reference
value = new Vector( X=1, Y=2, X=3 ); 

//// * Can't modify an immutable object
value.X = 123; 

//// * Immutable references can't be nulled
value = null; 

Essentially everything between the { } is a constructor, and everything that's constructed should be an expression (see Length in the example above). This should allow the 'with' operator that's used in F# to work here too, e.g.
let newVector = { oldVector with X = 3 );
let newVector = { oldVector with X = X + 1 );

If you wanted to have a mutable reference to a record-type in a class you would have to explicitly opt-in:
class AClass
     private mutable Vector vector;
Clearly this isn't a small job, but what I like about it is that it allows much simpler use of immutable types, it removes a lot of the common mistakes and the excessive typing when writing setter methods. It also doesn't encroach on classes or structs (other than that mutable option), and so it should ensure that backwards compatibility is 'relatively' easy.
Apr 7, 2014 at 11:51 PM
@louthy, in what does the already implemented language features do not address this?
public class Vector(float x, float y, float z)
    public float X { get; } = x;
    public float Y { get; } = y;
    public float Z { get; } = x;

    public Vector Add(Vector value) => new Vector(this.X + value.X, this.Y + value, this.Z + value.Z);
Apr 8, 2014 at 1:02 AM
In an object-oriented framework which from the beginning recognized strong distinctions among mutable value holders, immutable value holders, and entities, such distinctions could improve the semantics of many operations, and could also allow a variety of useful optimizations. For example, if the framework knows that two object instances are immutable value holders, and they are compared against each other and found to be be equal, the framework could note that both objects belong to the same equivalence class; during the next GC cycle, the framework could make all variables of type "reference to immutable value holder" point to the same instance. Such equivalence handling, if applied at the framework level, could be done quite cheaply without having to construct weak references (the only way an equivalence would keep alive an object that otherwise wouldn't be would be when it allowed another object to be collected). Additionally, having a recognized distinction between "reference to entity", "reference to sharable immutable value", and "reference to unshared mutable value" would eliminate much of the need to distinguish "deep copy" and "deep equality" from "shallow copy" and "shallow equality", and allow a compiler to instead simply generate automatic code which could handle copying and comparison.

I'm not sure what the proposed type would add, but distinguishing among different kinds of objects and references would certainly be a major plus in a new framework design, and could still be helpful in .NET.