A place to keep my thoughts on programming

July 23, 2011 .net ,

Simple Immutable objects

I'm currently at #monospace and over lunch was discussing message passing with @ackenpacken and @briandonahue. I was lamenting that to create an immutable object in C# was just a lot harder than a mutable one. You either have to create a builder of sorts or create very verbose constructors and never mind trying to derive a new immutable instance with just one field changed. I suggested that if only private setters could be used with object initializers, this would be solved and realized that I could just use anonymous objects as my initializers and so after finishing with talks for the day I coded up a proof of concept.

// create a new data class
public class Person {
  public int Id { get; private set; }
  public string Name { get; private set; }

So this is a perfectly good immutable object. So good, we can't even initialize it. Enter Droog.ImMutie.Immutable:

// create and instance
var person = Immutable.Create<Person>(new {Id = 43, Name = "Bob"});

The argument to Immutable.Create is simply object, so we can pass in an anonymous object with whatever properties we want. Create then provides and instance and copies over values on property name and type match. And if we want to change the Name?

// derive new instance with different name (using extension method)
person = person.With(new {Name = "Robert"});

With let's you provide a new anonymous object, will clone the previous instance and then overwrite each newly provided field by name/type match.

Very simple, no error checking, not the most efficient code, but it works and you can get it from github 🙂

3 to “Simple Immutable objects”

  1. tobi says...

    You don't seem to value strong typing very much.

  2. arne says...

    Curious what got you to that conclusion, as I personally think that I'm rather beligerent about strong typing in general. Yes, this is one place where I'm using anonymous types to get around a limitation of the framework to express immutability in a simple and concise manner, but trust me, it's not because i have a love for ever passing object to anything.

  3. tobi says...

    I said this because when you change the immutable class without manually changing all call sites of ".With", you will get an error at runtime, not at compile time.
    I found it is a better tradeoff to allow mutation and treat immutability as a guideline, and not be strict about it. If I know that an instance is not shared, I just mutate it. In practice this is not a hard problem because instances only get mutated in the vicinity of their creation (usually just for convenience / reduction of LOC). Once they are shared, I just don't change them. Easy pattern.

Leave a comment