Creating an immutable value object in C# - Part IV - A class with a special value
Luca -
☕ 2 min. read
Other posts:
-
- Part II - Making the class better
- Part III - Using a struct In the last post we looked at structs as ways to implement immutable value objects and we discovered that they have several issues.
A good thing about the struct implementation was the introduction of an explicit ‘special value’ instead of ‘null’. I personally like doing that because it forces me to think about what are the special values in my domain instead of blindly rely on null and its semantics. Plus, it also works where null breaks down, when there are multiple special values.
Having explicit special values is obviously not related to structs in any way. You can use the same pattern with classes as well, but you have to manage ‘null’ values that can enter your API. Here is how I did it for the DateSpan class.
First I defined an utility function to manage null values:
public static void CheckNull<T>(T t) { if (t == null) throw new ArgumentNullException(); }
Then I had to check my null precondition for each parameter of my API. I.E.
public DateSpan Intersect(DateSpan other) { Utils.CheckNull(other); ... }
Most importantly I now have to check for null in ‘Equals’ and ‘==’:
public override bool Equals(object obj) { // Interesting choice, null is not valid in this domain
Utils.CheckNull(obj); if (this.GetType() != obj.GetType()) return false; DateSpan other = obj as DateSpan; return other.End == End && other.Start == Start; }
<pre class="code"><span style="color:rgb(0,0,255);">public</span> <span style="color:rgb(0,0,255);">static</span> <span style="color:rgb(43,145,175);">Boolean</span> <span style="color:rgb(0,0,255);">operator</span> ==(<span style="color:rgb(43,145,175);">DateSpan</span> v1, <span style="color:rgb(43,145,175);">DateSpan</span> v2) {
<span style="color:rgb(43,145,175);">Utils</span>.CheckNull(v1);
<span style="color:rgb(43,145,175);">Utils</span>.CheckNull(v2);
<span style="color:rgb(0,0,255);">return</span> (v1.Equals(v2));
}</pre>
So now we have an immutable value object, represented as a class, with checks for nulls and a special value (not shown above because it is essentially the same as for structs). So, does this work?
It does, but it is cumbersome to write. And if it is too cumbersome, I already know that I'm not going to use it. I might start doing it, but I would soon give up. Are there ways to ease the pain?
One way would be to use snippets to help in writing the code. Snippets in this case have a couple of problems:
* It is not easy to ‘snippify' the logic inside ‘Equals', ‘GetHashcode' and such
* It makes easy to write the code, but still it is hard to read it and maintain it
In the next post we'll look at a better solution.
0 Webmentions
These are webmentions via the IndieWeb and webmention.io.
6 Comments
Comments
Geek Lectures - Things geeks s
2007-12-28T18:51:11ZPingBack from http://geeklectures.info/2007/12/28/creating-an-immutable-value-object-in-c-part-iv-a-class-with-a-special-value/
David V. Corbin
2007-12-28T18:53:36ZWhy are you ignoring the power of Guidance Automation to create all of the classes?????
onovotny
2007-12-28T19:47:32ZShouldn't you simply return false for equality if the other value is null instead of throwing?
lucabol
2007-12-28T22:49:37ZDavid: because I barely know what it is ;-)
Anyhow, I think there is a simpler solution. I'll post it later.
Onovotny: yes, that is usually the recommended way. In my case, I don't want for these objects to ever be null. If one of them is null, it means that there is something wrong in my app and I want to know it. Hence the exception.
Charlie Calvert's Community Bl
2008-01-03T02:13:41ZWelcome to the thirty-eighth Community Convergence. These posts are designed to keep you in touch with
Tales from the Evil Empire
2008-01-16T18:36:55ZFor some reason, there's been a lot of buzz lately around immutability in C#. If you're interested in