BT

New Early adopter or innovator? InfoQ has been working on some new features for you. Learn more

C# Futures: Immutable Classes

| by Jonathan Allen Follow 131 Followers on Jun 02, 2015. Estimated reading time: 4 minutes |

In the last of our C# Futures series, we look at proposal 159, which would add compiler support for immutable classes. While it has always been possible to create immutable types in C#, and C# 6 makes is even easier, there is currently no way to say “this class is immutable” and have the compiler verify the claim.

This might not seem like it is important, as it is usually not very difficult to manually inspect the class. But without some sort of claim to immutability, it can be hard to know the developer’s intentions. Application developers may make certain assumptions, like the class is safe to use in a multi-threaded context, only to discover that in version 2 the library author added a setter or other mutable, non-thread safe feature.

Proposal 159 would add an “immutable” keyword or attribute that explicitly says the type cannot be mutated in any way. Furthermore, an immutable object can only reference other immutable objects.

Immutable objects would also have restrictions placed on their constructor. Specifically, they can’t call methods using the “this” variable as that could ‘leak’ the object before it was fully constructed, thus breaking the promise of immutability. Whether such leaking should be an error or just a warning is debatable. Sam Harwell writes,

I would prefer this be a warning. While unlikely and generally not recommended, it's hard to state deterministically that no one will need to be able to write code like this.

Immutable vs Pure

At first glance it may seem like Immutable and Pure do the same thing, but there are some important differences.

  • A Pure object can have a reference to an object not marked as Pure. As mentioned before, Immutable objects cannot.
  • A Pure method cannot visibly change the state of anything. That includes both the current object and any parameters.
  • A Pure method or property can change internal state. For example, it can cache the result of a calculation to be reused later. This doesn’t violate the promise because outside observers can’t see the change. Again, an immutable object doesn’t have this option.
  • A method on an Immutable object only promises that object won’t be changed. It is allowed to modify the state of any parameters.

Given these differences, you would expect many objects to be both Immutable and Pure.

Generics and Immutable

Generic types would be able to support Immutable. Doing so usually require each type argument to have also have an immutable constraint. This rule is, however, debatable. Some think that you can infer immutability on the type arguments without have to explicitly list them out.

Cheating

It is recognized that there will be times when you need to cheat the type system. For example, an ImmutableArray is a wrapper around a normal array. Under the basic rules of this proposal that wouldn’t be allowed. In order to address this use case, you would be able to further annotate the class to say that you are consciously violating the rule and have thought through the repercussions. This is akin to use the “unsafe” keyword, which was actually proposed for this role.

Since “unsafe” already has another meaning, other keywords are being considered. So far “mutable” is the top contender, but no one is particularly happy with it either.

readonly – implicit or explicit

In an immutable object, every field has to be semantically readonly. Some developers think this should be implied, which would make the code less verbose. Others think that, like static in a static class, every field should be explicitly marked.

Internal or Externally Verified

An important thing to consider is where immutability will be enforced. Some are arguing that, like Code Contracts and the Pure attribute, that is should be handled by an external analyzer. This would allow teams to decide whether or not they care about programmatically enforcing immutability.

Other developers are arguing that is exactly why it shouldn’t be handled by an external tool. They want the compiler to make the checks, which would ensure that it couldn’t be accidentally turned off.

Jared Parsons of Microsoft writes,

I don't think an analyzer is the right solution here though. Analyzers are great at enforcing a set of rules, or even to a degree a dialect of C#, within a single C# project. I control the compilation I can pick what analyzers I want to use.

Analyzers are less effective when there is a need to enforce rules across projects. In particular when those projects are owned by different people. There is no mechanism for enforcing that a given project reference was scanned by a particular analyzer. The only enforcement that exists is a hand shake agreement.

This would be a different promise that the Pure attribute, which only says that an object has no methods or properties that can “make any visible state changes”.

Rate this Article

Adoption Stage
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Discuss

Login to InfoQ to interact with what matters most to you.


Recover your password...

Follow

Follow your favorite topics and editors

Quick overview of most important highlights in the industry and on the site.

Like

More signal, less noise

Build your own feed by choosing topics you want to read about and editors you want to hear from.

Notifications

Stay up-to-date

Set up your notifications and don't miss out on content that matters to you

BT