Geeks With Blogs
David Blomqvist

Last Friday, my and my colleagues were discussing structs vs classes. I said that that a struct can be made immutable and that is one difference from a class. They did not agree with me in this and said that both classes and structs can be made immutable by building them immutable (by having  only read only members) but there is not language support for immutable objects. I on the other hand thought that since struct is a value type, making a struct object read only should make it immutable. It cannot be changed. But a class on the other hand is a reference type and thus a class object that is read only should be possible to change the contents of but not the reference itself. This would mean that there is language support in C# for immutable struct objects but not immutable class objects. Or to be vclear, this is not only a discussion about immutabilityu but also on how const  and readonly affects struct and class.

But they persisted and said that I was wrong and after a while I gave up on i, since they are better at coding than me. But it didn’t seem to be corrects what they said. So now I had to write some code now to try it out. Here we go:

(non compiling code is commented out and the compiler message is written above)

 

   1: public class TheClass
   2: {
   3:     public TheClass(int x, int y)
   4:     {
   5:         _x = x;
   6:         _y = y;
   7:     }
   8:  
   9:     public int _x;
  10:     public int _y;
  11: }
  12:  
  13:  
  14: struct TheStruct
  15: {
  16:     public TheStruct(int x, int y)
  17:     {
  18:         _x = x;
  19:         _y = y;
  20:     }
  21:  
  22:     public int _x;
  23:     public int _y;
  24: }
  25:  
  26: class Client
  27: {
  28:     readonly TheStruct theStruct = new TheStruct(1, 2);
  29:     readonly TheClass theClass = new TheClass(1, 2);
  30:  
  31:     void ModifyStruct()
  32:     {
  33:         // Members of readonly field 'TheTestLib.Client.theStruct' cannot be modified (except in a constructor or a variable initializer)
  34:         // theStruct._x = 15;  
  35:  
  36:         // A readonly field cannot be assigned to (except in a constructor or a variable initializer)
  37:         // theStruct = new MyStruct(7, 18);
  38:  
  39:         // this works fine
  40:         theClass._x = 15;
  41:         theClass._y = 66;
  42:  
  43:         // A readonly field cannot be assigned to (except in a constructor or a variable initializer)
  44:         // theClass = new MyClass(7, 18);
  45:     }
  46: }

So. It turned out that by declaring your struct object readonly it becomes read only You cannot change the contents and you cannot change the object. The class on the other hand behaved as I expected. You can change the contents, but not the reference. This does not however mean that it is immutable since it is ok to do this:

We add this method to the struct:

public void IncreaseX()
{
    _x++;
}

And then try to call it from our client.

theStruct.IncreaseX();

this work fine. So the objects it read only, but it can change itself. Not immutable. How about const? Can we use that? While readonly gives you runt time read only, const gives you compile time read only. We get the compiler error
"The type 'TheTestLib.MyStruct' cannot be declared const".

Just for completeness we can try to use const on the class. This does not work either, we get the error:
"A const field of a reference type other than string can only be initialized with null."

 So to me it looks like we do not have any language support for immutability in C# with one clear keywor. But you  have to build  immutable classes adn structs, by using patterns. Like when building singletons for example. And I also learned some about the different behaviour of structs vs classes.

Please comment if you find any errors or if you have anything to add.

 

 

Posted on Monday, June 15, 2009 10:13 AM | Back to top


Comments on this post: Struct vs class and immutability

# re: Struct vs class and immutability
Requesting Gravatar...
That's a really helpful example, thanks.
Left by Rob on Jun 15, 2009 7:36 PM

# re: Struct vs class and immutability
Requesting Gravatar...
If you add readonly to lines 22 and 23 your struct is truely immutable, even from within the struct. Whether that makes any difference to the way the framework treats the type I don't know.
Left by Derek Fowler on Jun 16, 2009 1:03 AM

# re: Struct vs class and immutability
Requesting Gravatar...
The readonly effectively makes it a constant though for immutable structs. ( if you can set X and Y its mutable)

this is a mutable struct
struct TheStruct
15: {
16: public TheStruct(int x, int y)
17: {
18: _x = x;
19: _y = y;
20: }
21:
22: public int _x;
23: public int _y;
24: }

An immutable struct would have private fields and only get variables.
Left by Ben on Jan 19, 2010 5:31 PM

# re: Struct vs class and immutability
Requesting Gravatar...
The immutable version of your class would look like:

public class TheClass
{
public TheClass(int x, int y)
{
_x = x;
_y = y;
}

public readonly int _x;
public readonly int _y;
}

By specifying _x and _y as readonly, they can only be initialized in the constructor or a type initializer.

You could also make it immutable by simply making _x and _y private and exposing them through readonly properties, but using readonly is more explicit.

Personally I do both, so the implementation is encapsulated from people using your class. i.e.

public class TheClass
{
private readonly int _x;
private readonly int _y;

public TheClass(int x, int y)
{
_x = x;
_y = y;
}

public int X { get { return _x; } }
public int Y { get { return _y; } }
}
Left by Christian Coish on Nov 30, 2010 4:18 AM

Your comment:
 (will show your gravatar)


Copyright © blomqvist | Powered by: GeeksWithBlogs.net