5

I have been reading a lot of literature lately surrounding Value Types & Reference Types, and their differences. This question surrounds the topic of mutability and immutability of value types.

Based on what I have read, it seems that value types in .NET should be written in such a fashion that they are immutable; that is, once they have been assigned a value, the value of that type in memory never changes. Only subsequent copies of the type may construct new instances in memory with new values based off the original. It would seem that mutability in .NET is evil.

To clarify the understanding of immutability (for my own sanity, and for others), I have demonstrated this below:

DateTime and TimeSpan are examples of immutable structs because once a value has been assigned to an instance, that instances value cannot change, this is evident through readonly properties:

DateTime dt = new DateTime();
DateTime newdt = dt.AddDays(2); // Okay, new value stored in newdt
newdt.Year = 1945; // Error, cannot write to readonly property

Immutability can however be confusing when looking ar primitive types such as Int32, Double or Char, because the types appear to be mutable, but my gut feeling is that actually, immutability is handled transparently via the CLR; take for example the following operations (I've commented in some very basic x86 equivalent to understand how immutability is handled in terms of a primitive type)

int x = 0;

// xor eax, eax;     'clear register to 0
// push eax;         'push eax (0) onto the stack

x = 5;

// pop eax;          'pop stack (0) into eax
// mov eax, 5;       'eax = 5
// push eax;         'push eax (5) onto the stack

x++;

// pop eax;          'pop stack (5) into eax
// add eax, 1;       'eax = 5 + 1
// push eax;         'push eax (6) onto the stack

All well and good so far; Microsoft appear to be doing a good job of implementing immutability into their value types; but then we begin to find the bad apples, and suble nuances which make mutability look okay and lul developers into a false sense of security!

I'm talking about Point, Size, Rectangle (and a few others) in the System.Drawing namespace.

All of a sudden we're given the ability to mutate a value type by it's properties, and I have a theory as to why this is possible; take for example the following code

Point p = new Point();
p.X = 100;
p.Y = 200;

// Immutability (had it been implemented here) might infer the following usage

Point p = new Point(100, 200);
Point p2 = p.AddXY(200, 300);

However as stated I had a theory as to why these structures are mutable:

  1. Microsoft just wanted to make it easier to work with these structures.
  2. They are interoperable with native GDI/GDI+ calls, so their behavior was designed around their native C/C++ counterparts.

So finally my questions:

  1. Have I fully covered and understood immutability and mutability?
  2. Should developers aim to build immutable structs as a rule?
  3. When is it acceptable to build mutable structs?
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
  • There is lots and lots about this on google: https://www.google.at/search?q=c%23+struct+mutability+consistency – ASA Sep 01 '14 at 08:16
  • @ErenErsönmez I've read that article, but even then I say a lot of opinion as to why mutability may be considered a design decision rather than just "evil". – Matthew Layton Sep 01 '14 at 08:22
  • I found mutating *methods* problematic. Merely having public mutable fields or properties with a setter isn't a big issue. – CodesInChaos Sep 01 '14 at 08:39
  • http://stackoverflow.com/questions/8920080/why-are-system-windows-point-system-windows-vector-mutable – Yuval Itzchakov Sep 01 '14 at 08:39

2 Answers2

6

The issue of mutability is not one of value vs reference type. There are examples for both. Take System.String as an example for an immutable class as well as your example of System.Drawing.Point as an example of a mutable struct.

Mutable vs. immutable is a design decision based on the usage of the type. Whether it's a reference or a value type is another design decision that is not dependent on the former.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
2

Hmmm ... This will probably be closed soon, but here's my view on this.

  1. Yep, seems like you're understanding immutability vs. mutability.
  2. Should is a big word. Developers should be aware of the differences, care enough to know their trade, and have the common sense to ask themselves : what do I need from this specific struct.
  3. Acceptable ? I guess when you need it. The question of when do you need one is a whole different question.

Usually you use structs to hold some properties or primitives types. There are articles about what you should and should not have in your structs, in order for them to end on the heap or the stack, but that's out of the scope here.
If you have a compelling reason to use a mutable struct, and you document it so the next developer will know why, it's ok.
If on the contrary, you don't care, and documentation is not high your list, well, it doesn't really matter what's acceptable or not :).

Noctis
  • 11,507
  • 3
  • 43
  • 82