David Blomqvist

  Home  |   Contact  |   Syndication    |   Login
  13 Posts | 1 Stories | 51 Comments | 0 Trackbacks

News

Archives

Post Categories

Blogs

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.

 

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
posted on Monday, June 15, 2009 10:13 AM

Feedback

# re: Struct vs class and immutability 6/15/2009 7:36 PM Rob
That's a really helpful example, thanks.

# re: Struct vs class and immutability 6/16/2009 1:03 AM Derek Fowler
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.

# re: Struct vs class and immutability 1/19/2010 5:31 PM Ben
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.

# re: Struct vs class and immutability 11/30/2010 4:18 AM Christian Coish
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; } }
}

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: