5

When coding C# I often find myself implementing immutable types. I always end up writing quite a lot of code and I am wondering whether there is a faster way to achieve it.

What I normally write:

public struct MyType
{
 private Int32 _value;
 public Int32 Value { get { return _value;} }
 public MyType(Int32 val)
 {
 _value = val;
 }
}
MyType alpha = new MyType(42);

This gets fairly complicated when the number of fields grows and it is a lot of typing. Is there a more efficient way for doing this?

asked Aug 29, 2011 at 22:58
4
  • 2
    You should also mark the _value field as readonly. Also, is there a particular reason why you are using a struct instead of a class? Commented Aug 29, 2011 at 23:06
  • @adrianbanks: no specific reason. It's just that in most cases I'm more interested in the values, rather than in behaviour Commented Aug 29, 2011 at 23:07
  • @yas4891: in that case, make sure you read Choosing between classes and structures. Commented Aug 29, 2011 at 23:08
  • 1
    This can be driven to extremes that ultimately end up not actually getting the job done. The point of writing a program is to mutate state. If you don't, you can never figure out when you're done and never actually accomplish anything. Sure, don't mutate a struct. Mutating a class object is progress, never hesitate to accomplish that. Commented Aug 29, 2011 at 23:53

3 Answers 3

5

The only way I can suggest of writing less code is to use something like ReSharper to auto-generate the code for you. If you start with something like:

public class MyType
{
 private int _value;
}

you can then generate "read-only properties" to give:

public class MyType
{
 private int _value;
 public int Value{get {return _value;}}
}

followed by generate constructor to give:

public class MyType
{
 private int _value;
 public int Value{get {return _value;}}
 public MyType(int value)
 {
 _value = value;
 }
}

The generation steps are 8 key presses in total.


If you really want an unmodifiable immutable class, I would declare it as such:

public sealed class MyType
{
 public int Value{get {return _value;}}
 private readonly int _value;
 public MyType(int value)
 {
 _value = value;
 }
}

This makes the class non-derivable (meaning that a sub-class cannot modify its inner state), and the _value property assignable only during construction. Unfortunately, ReSharper doesn't have code generation for this pattern, so you would still have to construct (most of) it manually.

answered Aug 29, 2011 at 23:16

3 Comments

+1 for making the class sealed. Immutable classes designed for inheritance make no sense at all.
I've accepted this answer because it made the type sealed and the value readonly.
Immutability and inheritance are not mutually exclusive, especially when dealing with polymorphism. As an example, see the System.Linq.Expressions namespace.
4

You could simplify it a little with automatic properties and a private setter as below:

public struct MyType
{ 
 public Int32 Value { get; private set; }
 public MyType(Int32 val)
 {
 Value = val;
 }
}
answered Aug 29, 2011 at 23:01

7 Comments

This prevents the use of readonly, though - while the OP didn't have that, it would help to enforce the immutability constraint.
That's a bit of an academic consideration in my opinion.
In a larger class, over time, it's very difficult to prevent another developer from calling your setter... Even a non-readonly backing field does not make it obvious that the intent is to be immutable. While there's no true immutable types in C#, making it readonly and having no setter definitely makes the intent much more clear.
I guess I'm used to being the boss - the developer in question doing that without justification wouldn't be a developer around here for long ;)
Sounds like you need to find a better boss ;)
|
1

Code snippets at the rescue! Save this xml as "immutable.snippet", then go to Visual Studio, select Tools, Code Snippets Manager and import it. That's it! Now write "immutable" and hit TAB twice and you have your immutable type.

The actual code in the snippet is based on @adrianbanks answer.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
 <Header>
 <SnippetTypes>
 <SnippetType>Expansion</SnippetType>
 </SnippetTypes>
 <Title>Immutable type (C#)</Title>
 <Author>Alfonso Cora</Author>
 <Description>Creates an immutable type</Description>
 <HelpUrl>http://stackoverflow.com/questions/7236977/how-to-efficiently-implement-immutable-types</HelpUrl>
 <Shortcut>immutable</Shortcut>
 </Header>
 <Snippet>
 <Declarations>
 <Literal Editable="true">
 <ID>type</ID>
 <ToolTip>The type on which this immutable type is based.</ToolTip>
 <Default>int</Default>
 <Function>
 </Function>
 </Literal>
 <Literal Editable="true">
 <ID>class</ID>
 <ToolTip>The name of the immutable type.</ToolTip>
 <Default>MyImmutableType</Default>
 <Function>
 </Function>
 </Literal>
 </Declarations>
 <Code Language="csharp"><![CDATA[public sealed class $class$
{
 public $type$ Value{get {return _value;}}
 private readonly $type$ _value;
 public $class$($type$ value)
 {
 _value = value;
 }
}]]></Code>
 </Snippet>
 </CodeSnippet>
</CodeSnippets>
answered Aug 30, 2011 at 3:26

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.