tags:

views:

780

answers:

6

How do I find out if a class is immutable in C#?

+1  A: 

To my knowledge, unless it's explicitly documented, there is no way to determine whether a class is immutable or not in C#.

You can, however, use Reflection to check for the existence of Setters on properties; however, lack of setters does not guarantee immutability as internal state may change the values of these properties whether you can explicitly set them or not.

Additionally, checking for the 'IsInitOnly' flag for all the class's fields, again using Reflection, might indicate immutability, but it doesn't guarantee it.

Edit: Here's a similar question, asked regarding the Java language, whose answer also applies here.

Erik Forbes
A: 

The only help you get from the runtime is if all the fields in the class are annotated with "readonly". [Edit, see @ShuggyCoUk] And even then the CLR will let you write over it. I just verified it. Ugh.

You can get the FieldInfo objects from the class via reflection and check IsInitOnly.

codekaizen
+1  A: 

You cannot, you can only guess. If all fields are readonly the the instances will be immutable once the constructor finishes. This is important, if you had the following it would appear mutable to the instance bar.

class Foo
{
    public readonly int X
    public readonly int Y
    public Foo(int x, int y, Bar bar)
    {
        this.X = x; 
        bar.ShowYourself(this);
        this.Y = y;
        bar.ShowYourself(this);
    }
}

However if a field on the supposedly immutable class was a collection (and was not read only) then calling the class immutable would likely be incorrect (since it's state can change)

Note that even if all fields are readonly reflection is allowed to modify the fields.

Checking for no setters on properties will be a very poor heuristic indeed.

ShuggyCoUk
A: 

Via code, I'm not sure, but afaik if you look at the IL of another immutable type, such as a string you will not see a newobj IL instruction (you'll see ldstr for strings), perhaps inspecting the IL of the creation may be one way to tell, just a guess...

RandomNoob
Of course, even string isn't **strictly** immutable (see my answer). Also, string is an unusual type: in common with arrays, it has special treatment as variable length - so most bets are off when comparing to string.
Marc Gravell
Good to know. Thanks Marc
RandomNoob
+1  A: 

Part of the problem is that "immutable" can have multiple meanings. Take, for example, ReadOnlyCollection<T>.

We tend to consider it to be immutable. But what if it's a ReadOnlyCollection<SomethingChangeable>? Also, since it's really just a wrapper around an IList I pass in to the constructor, what if I change the original IList?

A good approach might be to create an attribute with a name like ReadOnlyAttribute and mark classes you consider to be read-only with it. For classes you don't control, you can also maintain a list of known types that you consider to be immutable.

EDIT: For some good examples of different types of immutability, read this series of postings by Eric Lippert: http://blogs.msdn.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx

Neil Whitaker
+8  A: 

There is ImmutableObjectAttribute, but this is rarely used and poorly supported - and of course not enforced (you could mark a mutable object with [ImmutableObject(true)]. AFAIK, the only thing this this affects is the way the IDE handles attributes (i.e. to show / not-show the named properties options).

In reality, you would have to check the FieldInfo.IsInitOnly, but this only applies to truly 100% immutable types (assuming no reflection abuse, etc); it doesn't help with popsicle immutability, nor things that are immutable in practice, but not in their implementation; i.e. they can't be made to be publicly mutable, but in theory the object supports it.

A classic example here would be string... everyone "knows" that string is immutable... of course, StringBuilder does mutate a string under the bonnet. No, seriously...

It is so hard to define immutability given this, let alone robustly detect it...

Marc Gravell
It would be nice if there were a keyword on class definitions - maybe something like 'public immutable class SomeClass { ... }'
Erik Forbes
And then have the compiler do some static analysis to detect external state changes wherever possible - and where impossible, let the runtime throw an exception.
Erik Forbes
++ to that, and then make it the default!
ShuggyCoUk
I hope that immutability will be a big focus of C# 5.0
Marc Gravell