{"id":2731,"date":"2008-11-26T11:11:00","date_gmt":"2008-11-26T11:11:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/nullable-structs-an-interesting-gotcha\/"},"modified":"2016-07-28T10:49:28","modified_gmt":"2016-07-28T10:49:28","slug":"nullable-structs-an-interesting-gotcha","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/nullable-structs-an-interesting-gotcha\/","title":{"rendered":"Nullable Structs &#8211; An interesting &#8216;Gotcha&#8217;"},"content":{"rendered":"<p class=\"MsoNormal\">One of the interesting new features in C# 2.0 was nullable valuetypes.&#160; Using these, you can set valuetypes to a value, or null.&#160; Their usage is entirely straightforward.&#160; For instance, to use a nullable int simply declare a variable of type int?, and then set it to a value or null.<\/p>\n<p class=\"MsoNormal\">Behind the scenes, nullable valuetypes are implemented as generic structs of type Nullable&lt;T&gt;.&#160; When you write:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int? i = 2;<\/p>\n<p class=\"MsoNormal\">What you&#8217;re really writing is:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Nullable&lt;int&gt; i = new Nullable&lt;int&gt;(2);<\/p>\n<p class=\"MsoNormal\">When you assign a value to a pre-existing nullable int, like so:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; i = 4;<\/p>\n<p class=\"MsoNormal\">you&#8217;re really writing:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; i = new Nullable&lt;int&gt;(4);<\/p>\n<p class=\"MsoNormal\">And when you &#8216;get&#8217; the value, like so:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int j = i;<\/p>\n<p class=\"MsoNormal\">What you&#8217;re really writing is:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int j = i.Value;<\/p>\n<p class=\"MsoNormal\">The Value is a get property, and assignment is by creating a new instance of Nullable&lt;T&gt;.&#160; This is similar to strings in C#: presenting a reference type by valuetype semantics.<\/p>\n<p class=\"MsoNormal\">This is all fine for primitives like int, double, etc. But when using structs, an interesting problem is created that lets light in on the &#8216;magic&#8217; of nullable valuetypes.<\/p>\n<p class=\"MsoNormal\">Let&#8217;s say I have a struct Point, implemented as so:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160; struct Point<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; public int x, y;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; public Point(int px, int py)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; x = px; y = py;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; public override string ToString()<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &#8220;(&#8221; + x + &#8220;, &#8221; + y + &#8220;)&#8221;;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">Then, I write a program that creates an int and a Point, and alter them slightly:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int i = 3;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(++i);&#160;&#160; \/\/increment then print it<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Point p = new Point(2, 4);<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p.x = 1; Console.WriteLine(p);&#160; \/\/move left then print it<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.ReadLine();<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">No problems here.&#160; The int and the Point will be altered as expected. &#160;&#160;Now I decide that I want my int and Point to be nullable.&#160; So I simply add two question marks, producing this program:<\/p>\n<p class=\"MsoNormal\">&#160;&#160; &#160;&#160;&#160;&#160;&#160;static void Main(string[] args)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int? i = 3;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(++i);&#160;&#160; \/\/increment then print it<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Point? p = new Point(2, 4);<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p.x = 1; Console.WriteLine(p);&#160; \/\/move left then print it<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;Console.ReadLine();<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">But this won&#8217;t compile.&#160; The int? part is fine, but for the Point? part I get the error: <i>&#8220;&#8216;System.Nullable&lt; Point&gt;&#8217; does not contain a definition for &#8216;x'&#8221;<\/i>.&#160; No problem, I&#8217;ll just edit it like so:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int? i = 3;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(++i);&#160;&#160; \/\/increment then print it<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Point? p = new Point(2, 4);<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p. Value.x = 1; Console.WriteLine(p);&#160; \/\/move left then print it<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.ReadLine();<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">Now you get a different compile error: <i>&#8220;Cannot modify the return value of &#8216;System.Nullable&lt;.Point&gt;.Value&#8217; because it is not a variable&#8221;<\/i>.&#160; This happens because Nullable&lt;T&gt;.Value has no set accessor method.<\/p>\n<p class=\"MsoNormal\">Nullable value types have this &#8216;limitation&#8217; for a very good reason.&#160;&#160; The same thing happens is you try to edit a struct in a List&lt;&gt; of structs.&#160; Consider an over-simplification of Nullable&lt;T&gt; with a bodged-in set accessor, like so:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160; class MyNullable&lt;T&gt;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; private T val;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; public T Value<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; set {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; val = value;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; get {<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return val;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160; }<\/p>\n<p class=\"MsoNormal\">If I create a MyNullable&lt;Point&gt; and use it:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MyNullable&lt;Point&gt; p = new MyNullable&lt;Point&gt;();<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p.Value = new Point(2, 1);<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p.Value.x = 2;<\/p>\n<p class=\"MsoNormal\">I get a compile error on the third line: <i>&#8220;Cannot modify the return value of &#8216;MyNullable&lt;Point&gt;.Value&#8217; because it is not a variable&#8221;.<\/i>&#160; This is because the statement p.Value.x = 2 is equivilent to:<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Point otherPoint = p.Value; otherPoint.x = 2;<\/p>\n<p class=\"MsoNormal\">Which doesn&#8217;t change the underlying p.val, because otherPoint is a <b><i>copy<\/i><\/b> of p.Val.&#160; So when C# gives us a compile error, it is merely protecting us from editing an irrelevent copy of the underlying Point.<\/p>\n<p class=\"MsoNormal\">In conclusion, nullable valuetypes are immutable.&#160; I think the C# designers intended programmers to never modify the value of a struct once one is created, nullable or not.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the interesting new features in C# 2.0 was nullable valuetypes.&#160; Using these, you can set valuetypes to a value, or null.&#160; Their usage is entirely straightforward.&#160; For instance, to use a nullable int simply declare a variable of type int?, and then set it to a value or null. Behind the scenes, nullable&#8230;&hellip;<\/p>\n","protected":false},"author":95472,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-2731","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2731","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/95472"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=2731"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2731\/revisions"}],"predecessor-version":[{"id":41705,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2731\/revisions\/41705"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=2731"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=2731"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=2731"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=2731"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}