How do I find out if a class is immutable in C#?
7 Answers
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...

- 1,026,079
- 266
- 2,566
- 2,900
-
1It would be nice if there were a keyword on class definitions - maybe something like 'public immutable class SomeClass { ... }' – Erik Forbes Jan 27 '09 at 00:46
-
1And 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 Jan 27 '09 at 00:46
-
1++ to that, and then make it the default! – ShuggyCoUk Jan 27 '09 at 00:59
-
23I hope that immutability will be a big focus of C# 5.0 – Marc Gravell Jan 27 '09 at 14:30
-
With NDepend I think you could get a static analysis process to warn you if a class with the ImmutableObject attribute is actually mutable. See http://codebetter.com/patricksmacchia/2008/01/13/immutable-types-understand-them-and-use-them/ – Anssssss Jan 10 '12 at 15:08
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

- 7,227
- 5
- 42
- 43
-
I don't see the ambiguity. A collection of type T holds things of type T as values. If I have a list of ten red Toyotas (or more precisely, a list of ten Vehicle Identification Numbers which happen to refer to red Toyotas), and I lock that list in a vault, there's no reason I should expect that action to prevent someone from painting the cars green (meaning the list would now have ten green cars). Locking the list in a vault would, however, prevent anyone from turning it into a list of ten Fords (since the manufacturer of a car is an immutable property). – supercat Dec 15 '11 at 18:18
-
@supercat, deep immutability allows code to provide guarantees that it otherwise could not. For example, data can be freely passed between threads without any worry of corruption. As another example, a data provider might have a cached list of objects that it provides to requestors but needs to guarantee that the objects it returns are always in their new, pristine state. If anything out there can modify them, then the provider will have to clone each one in order to guarantee they are clean each time. If it has deep immutability, it can simply return the list. – Neil Apr 04 '12 at 20:46
-
Certainly deep immutability can be useful, but I see no reason to expect an `ImmutableCollection
` to be deeply immutable unless `T` is either a deeply-immutable class or else a struct which contains, in itself or nested structs, nothing but primitives or deeply-immutable classes. I do wish .net had included a nice means of having "parallel" mutable and immutable versions of a class, so that one could easily copy data from an immutable instance to a mutable one, modify it, and copy the data to a new immutable instance. The closest one can come in some ways would be to... – supercat Apr 04 '12 at 22:05 -
...use a mutable struct as a data holder, and define an `ImmutableHolder
` class to hold it. Because copying a struct inherently copies all the fields, one could use generic methods to convert between the mutable and immutable forms (something like `MemberwiseClone` wouldn't be usable because the clone would have to be the same type as the original). Unfortunately, such an approach wouldn't allow for any useful inheritance, would require an extra level of indirection when accessing the fields of a struct held by an immutable instance, and would be rather awkward in general. – supercat Apr 04 '12 at 22:11
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.

- 36,004
- 6
- 77
- 101
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.

- 1
- 1

- 35,357
- 27
- 98
- 122
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.

- 26,990
- 7
- 84
- 140
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...

- 31,040
- 13
- 70
- 99
-
1Of 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 Jan 27 '09 at 00:46
Use it at your own risk. This will not work in case of cyclic dependency of classes (although a modification of it might work) and also it can give false negative results (i.e. if it returns true that means the class is immutable for sure, but if it returns false it may or may not be immutable). But it should work fine for most of the cases except for very convoluted classes.
using System.Reflection;
public static class StructUtils
{
public static bool IsImmutable(Type type, int depth = 5)
{
if (type == typeof(string) || type.IsValueType)
{
return true;
}
else if (depth == 0)
{
return false;
}
else
{
return type.GetFields()
.Where(fInfo => !fInfo.IsStatic) // Filter out statics
.Where(fInfo => fInfo.FieldType != type) // Filter out 1st level recursion
.All(fInfo => fInfo.IsInitOnly && IsImmutable(fInfo.FieldType, depth - 1)) &&
type.GetProperties()
.Where(pInfo => !pInfo.GetMethod.IsStatic) // Filter out statics
.Where(pInfo => pInfo.PropertyType != type) // Filter out 1st level recursion
.All(pInfo => !SetIsAllowed(pInfo, checkNonPublicSetter: true) && IsImmutable(pInfo.PropertyType, depth - 1));
}
}
private static bool SetIsAllowed(PropertyInfo pInfo, bool checkNonPublicSetter = false)
{
var setMethod = pInfo.GetSetMethod(nonPublic: checkNonPublicSetter);
return pInfo.CanWrite &&
((!checkNonPublicSetter && setMethod.IsPublic) ||
(checkNonPublicSetter && (setMethod.IsPrivate || setMethod.IsFamily || setMethod.IsPublic || setMethod.IsAbstract)));
}
}
Some sample classes which I used for testing:
public class Z
{
private readonly List<string> _s;
public int F { get; }
public readonly string K;
public const int Pi = 3;
public Z NextPtr { get; }
}
public class X
{
public Z Z { get; }
public readonly int C;
public string Cmp { get; }
}
public class W
{
public X Z { get; }
public readonly List<int> C1;
public readonly string Cmp1;
}
Got the following results:
> StructUtils.IsImmutable(typeof(Z))
true
> StructUtils.IsImmutable(typeof(X))
true
> StructUtils.IsImmutable(typeof(W))
false

- 23
- 4