{"id":178,"date":"2009-05-26T20:23:53","date_gmt":"2009-05-27T01:23:53","guid":{"rendered":"http:\/\/www.redrecondite.com\/blog\/?p=178"},"modified":"2013-04-30T16:58:57","modified_gmt":"2013-04-30T21:58:57","slug":"creating-immutable-data-classes-in-csharp-quickl","status":"publish","type":"post","link":"https:\/\/www.redrecondite.com\/blog\/2009\/05\/26\/creating-immutable-data-classes-in-csharp-quickl\/","title":{"rendered":"Creating Immutable Data Classes in C#&#8230; Quickly"},"content":{"rendered":"<p>Of late, I&#8217;ve been tempted by <a href=\"\/\/msdn.microsoft.com\/en-us\/fsharp\/default.aspx\">F#<\/a>.\u00a0 In reading articles and familiarizing myself with the language, there seems to be something truly interesting there, but I just don&#8217;t grok functional programming yet.<\/p>\n<p>One item in particular that I&#8217;ve seen is the <a href=\"\/\/research.microsoft.com\/en-us\/um\/cambridge\/projects\/fsharp\/manual\/spec2.aspx#_Toc207785609\">Record<\/a> data expression.\u00a0 This allows you to create an <a href=\"\/\/en.wikipedia.org\/wiki\/Immutable_object\">immutable<\/a> data structure, like so:<\/p>\n<pre name=\"code\" class=\"c#\">type Data = { Count : int; Name : string }\r\nlet data1 = { Count = 3; Name = \"Hello\"; }<\/pre>\n<p>Then, if at a later time you wish to change Count but keep Name the same, that&#8217;s absurdly simple.<\/p>\n<pre name=\"code\" class=\"c#\">let newData = data1 with Count = 4;<\/pre>\n<p>C#&#8230; does not have anything like this.\u00a0 To create a similar immutable data structure (including equality checking), you&#8217;d have to do something like this:<\/p>\n<pre name=\"code\" class=\"c#\">using System;\r\nusing System.Collections.Generic;\r\n\r\npublic class Data : IEquatable&lt;Data&gt;\r\n{\r\n    private readonly int mCount;\r\n    public int Count\r\n    {\r\n        get { return mCount; }\r\n    }\r\n\r\n    private readonly string mName;\r\n    public string Name\r\n    {\r\n        get { return mName; }\r\n    }\r\n\r\n    public Data( int aCount, string aName )\r\n    {\r\n        mCount = aCount;\r\n        mName = aName;\r\n        return;\r\n    }\r\n\r\n\r\n    public Data ChangeCount( int aCount )\r\n    {\r\n        return new Data( aCount, mName );\r\n    }\r\n\r\n    public Data ChangeName( string aName )\r\n    {\r\n        return new Data( mCount, aName );\r\n    }\r\n\r\n    public bool Equals( Data aOther )\r\n    {\r\n        bool lResult = false;\r\n        if ( aOther != null )\r\n        {\r\n            lResult = ( this.Count == aOther.Count &&\r\n                        this.Name == aOther.Name );\r\n        }\r\n        return lResult;\r\n    }\r\n\r\n    public override bool Equals( object aOther )\r\n    {\r\n        bool lResult = false;\r\n        if ( aOther is Data )\r\n        {\r\n            lResult = Equals( aOther as Data );\r\n        }\r\n        return lResult;\r\n    }\r\n\r\n    public override int GetHashCode()\r\n    {\r\n        return Name.GetHashCode();\r\n    }\r\n\r\n    public static bool operator ==( Data aLeft, Data aRight )\r\n    {\r\n        return EqualityComparer&lt;Data&gt;.Default.Equals( aLeft, aRight );\r\n    }\r\n\r\n    public static bool operator !=( Data aLeft, Data aRight )\r\n    {\r\n        return !EqualityComparer&lt;Data&gt;.Default.Equals( aLeft, aRight );\r\n    }\r\n}<\/pre>\n<p>That&#8217;s a lot of work!  In F#, what takes a single line takes 70 in C#.  And a lot of that is nasty, crufty copy-paste code.  And its easy to forget to change some things, like the Equals method.<\/p>\n<p>Well, let me correct myself.  That <b>would<\/b> be a lot of work&#8230; if I wrote that.  But I didn&#8217;t.  I just wrote this:<\/p>\n<pre name=\"code\" class=\"c#\">&lt;#\r\nthis.Namespace = \"Example\";\r\nthis.ClassName = \"Data\";\r\nthis.ClassScope = \"public\";\r\nthis.ImplementINotifyProperty = false;\r\nthis.HashCodeVariable = \"Name\";\r\nthis.Variables = new List&lt;Variable&gt;()\r\n{\r\n    new Variable( \"Count\", \"int\", Options.Immutable | Options.ChangeMethod ),\r\n    new Variable( \"Name\", \"string\", Options.Immutable | Options.ChangeMethod ),\r\n};\r\n#&gt;\r\n&lt;#@ include file=\"DataClass.tt\" #&gt;<\/pre>\n<p>What is this mysterious mumbo-jumbo?  That, sir (or madam), is T4: Microsoft&#8217;s <a href=\"\/\/msdn.microsoft.com\/en-us\/library\/bb126445.aspx\">Text Template Transformation Toolkit<\/a> (aka a code generator).  It is included in Visual Studio 2008, but it isn&#8217;t widely advertised.<\/p>\n<p>My DataClass.tt file is a horribly messy template that takes in the values I listed above, and translates them into the real source code example I pasted above.  Besides immutable data structures, it also supports mutable members, including support for INotifyPropertyChanged and [Member]Changed events.<\/p>\n<p>I&#8217;m rather liking this so far.  If it turns out that this code generation is a horrible idea, I can simply delete my .tt files and use my auto-generated .cs files from then-on with little loss.<\/p>\n<p>Note that the following source code is not well documented, and is not very error tolerant.  If you do something silly, chances are you&#8217;ll get an obtuse compilation error.  I recommend modifying it to suit your own needs.<\/p>\n<p><a href=\"\/\/www.redrecondite.com\/blog\/wp-content\/uploads\/2009\/05\/dataclasscodegenerator.zip\">Data Class Code Generator Source Code<\/a> (11 KB, requires Visual Studio 2008)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Of late, I&#8217;ve been tempted by F#.\u00a0 In reading articles and familiarizing myself with the language, there seems to be something truly interesting there, but I just don&#8217;t grok functional programming yet. One item in particular that I&#8217;ve seen is the Record data expression.\u00a0 This allows you to create an immutable data structure, like so: [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,12],"tags":[],"class_list":["post-178","post","type-post","status-publish","format-standard","hentry","category-c-sharp","category-development"],"_links":{"self":[{"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/posts\/178"}],"collection":[{"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/comments?post=178"}],"version-history":[{"count":10,"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/posts\/178\/revisions"}],"predecessor-version":[{"id":258,"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/posts\/178\/revisions\/258"}],"wp:attachment":[{"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/media?parent=178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/categories?post=178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.redrecondite.com\/blog\/wp-json\/wp\/v2\/tags?post=178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}