    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: NullableAttribute and C# 8</title>
        <link>https://members.accu.org/index.php/articles/2642</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #150 - April 2019</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c397/">o150</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-397/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+397/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;NullableAttribute and C# 8</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 04 April 2019 17:39:30 +01:00 or Thu, 04 April 2019 17:39:30 +01:00</p>
<p><strong>Summary:</strong>&nbsp;C# 8 will bring many new features. Jon Skeet investigates the metadata representation of Nullable Reference Types.</p>
<p><strong>Body:</strong>&nbsp;<h2>Background: Noda Time and C# 8</h2>

<p>C# 8 is nearly here. At least, itâ€™s close enough to being â€˜hereâ€™ that there are preview builds of Visual Studio 2019 available that support it. Unsurprisingly, Iâ€™ve been playing with it quite a bit.</p>

<p>In particular, Iâ€™ve been porting the Noda Time source code [<a href="#[Skeet-1]">Skeet-1</a>] to use the new C# 8 features. The master branch of the repo is currently the code for Noda Time 3.0, which wonâ€™t be shipping (as a GA release) until after C# 8 and Visual Studio 2019 have fully shipped, so itâ€™s a safe environment in which to experiment.</p>

<p>While itâ€™s possible that Iâ€™ll use other C# 8 features in the future, the two C# 8 features that impact Noda Time most are <em>nullable reference types</em> and <em>switch expressions</em>. Both sets of changes are merged into master now, but the pull requests are still available so you can see just the changes:</p>

<ul>
	<li>PR 1240: Support nullable reference types [<a href="#[Skeet-2]">Skeet-2</a>]</li>
	<li>PR 1264: Use switch expressions [<a href="#[Skeet-3]">Skeet-3</a>]</li>
</ul>

<p>The switch expressions PR is much simpler than the nullable reference types one. Itâ€™s entirely an implementation detailâ€¦ although admittedly one that confused docfx, requiring a few of those switch expressions to be backed out or moved in a later PR.</p>

<p>Nullable reference types are a much, much bigger deal. They affect the public API, so they need to be treated much more carefully, and the changes end up being spread far wide throughout the codebase. Thatâ€™s why the switch expression PR is a single commit, whereas nullable reference types is split into 14 commits â€“ mostly broken up by project.</p>

<h2>Reviewing the public API of a nullable reference type change</h2>

<table class="sidebartable">
	<tr>
		<td class="title">Nullable reference types</td>
	</tr>
	<tr>
		<td>
			<table class="journaltable">
				<tr>
					<td>C# 8 introduces nullable reference types, which complement reference types the same way nullable value types complement value types. You declare a variable to be a nullable reference type by appending a ? to the type. For example, string? represents a nullable string. You can use these new types to more clearly express your design intent: some variables must always have a value, others may be missing a value. [<a href="#[Microsoft]">Microsoft</a>]</td>
				</tr>
			</table>
		</td>
	</tr>

</table>

<p>So Iâ€™m now in a situation where Iâ€™ve got nullable reference type support in Noda Time. Anyone consuming the 3.0 build (and thereâ€™s an alpha available for experimentation purposes [<a href="#[NodaTime]">NodaTime</a>]) from C# 8 will benefit from the extra information that can now be expressed about parameters and return values. Great!</p>

<p>But how can I be confident in the changes to the API? My process for making the change in the first place was to enable nullable reference types and see what warnings were created. Thatâ€™s a great starting point, but it doesnâ€™t necessarily catch everything. In particular, although I <em>started</em> with the main project (the one that creates NodaTime.dll), I found that I needed to make more changes later on, as I modified other projects.</p>

<p><strong>Just because your code compiles without any warnings with nullable reference types enabled doesnâ€™t mean itâ€™s â€˜correctâ€™ in terms of the API you want to expose.</strong></p>

<p>For example, consider this method:</p>

<pre class="programlisting">
  public static string Identity(string input) 
    =&gt; input;</pre>
	
<p>Thatâ€™s entirely valid C# 7 code, and doesnâ€™t require any changes to compile, warning-free, in C# 8 with nullable reference types enabled. But it may not be what you actually want to expose. Iâ€™d argue that it should look like <em>one</em> of the options in Listing 1.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
// Allowing null input, producing nullable output
public static string? Identity(string? input) 
  =&gt; input;
 
// Preventing null input, producing non-nullable
// output
public static string Identity(string input)
{
  // Convenience method for nullity checking.
  Preconditions.CheckNotNull(input,
    nameof(input));
  return input;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>If you were completely diligent when writing tests for the code before C# 8, it should be obvious which is required â€“ because youâ€™d presumably have something like:</p>

<pre class="programlisting">
  [Test]
  public void Identity_AcceptsNull()
  {
    Assert.IsNull(Identity(null));
  }</pre>
  
<p><em>That</em> test would have produced a warning in C# 8, and would have suggested that the null-permissive API is the one you wanted. But maybe you forgot to write that test. Maybe the test you <em>would</em> have written was one that would have shown up a need to put that precondition in. Itâ€™s entirely possible that you write much more comprehensive tests than I do, but I suspect most of us have <em>some</em> code that isnâ€™t explicitly tested in terms of its null handling.</p>

<p>The important part take-away here is that even code that hasnâ€™t changed in appearance can change <em>meaning</em> in C# 8â€¦ so you really need to review any public APIs. How do you do that? Well, you could review the <em>entire</em> public API surface youâ€™re exposing, of course. For many libraries that would be the simplest approach to take, as a â€˜belt and bracesâ€™ attitude to review. For Noda Time thatâ€™s less appropriate, as so much of the API only deals in value types. While a full API review would no doubt be useful in itself, I just donâ€™t have the time to do it right now.</p>

<p>Instead, what I want to review is any API element which is impacted by the C# 8 change â€“ even if the code itself <em>hasnâ€™t</em> changed. Fortunately, thatâ€™s relatively easy to do.</p>

<h2>Enter NullableAttribute</h2>

<p>The C# 8 compiler applies a new attribute to every API element which is affected by nullability. As an example of what I mean by this, consider the code in Listing 2, which uses the <code>#nullable</code> directive to control the nullable context of the code.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
public class Test
{
#nullable enable
  public void X(string input) {}
 
  public void Y(string? input) {}
#nullable restore
 
#nullable disable
  public void Z(string input) {}
#nullable restore
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>The C# 8 compiler creates an internal <code>NullableAttribute</code> class within the assembly (which I assume it wouldnâ€™t if we were targeting a framework that already includes such an attribute) and applies the attribute anywhere itâ€™s relevant. So the code in Listing 2 compiles to the same IL as this:</p>

<pre class="programlisting">
  using System.Runtime.CompilerServices;
  public class Test
  {
    public void X([Nullable((byte) 1)]
      string input) {}
    public void Y([Nullable((byte) 2)]
      string input) {}
    public void Z(string input) {}}
  }</pre>
  
<p>Note how the parameter for <code>Z</code> doesnâ€™t have the attribute at all, because that code is still <em>oblivious</em> to nullable reference types. But both <code>X</code> and <code>Y</code> have the attribute applied to their parameters â€“ just with different arguments to describe the nullability. 1 is used for not-null; 2 is used for nullable.</p>

<p>That makes it relatively easy to write a tool to display every part of a libraryâ€™s API that relates to nullable reference types â€“ just find all the members that refer to <code>NullableAttribute</code>, and filter down to public and protected members.</p>

<p>Itâ€™s slightly annoying that <code>NullableAttribute</code> doesnâ€™t have any properties; code to analyze an assembly needs to find the appropriate <code>CustomAttributeData</code> and examine the constructor arguments. Itâ€™s awkward, but not insurmountable.</p>

<p>Iâ€™ve started doing exactly that in the Noda Time repository, and got it to the state where itâ€™s fine for Noda Timeâ€™s API review. Itâ€™s a bit quick and dirty at the moment. It doesnâ€™t show protected members, or setter-only properties, or handle arrays, and there are probably other things Iâ€™ve forgotten about. I intend to improve the code over time and probably move it to my Demo Code repository at some point, but I didnâ€™t want to wait until then to write about <code>NullableAttribute</code>.</p>

<p>But hey, Iâ€™m all done, right? Iâ€™ve explained how <code>NullableAttribute</code> works, so whatâ€™s left? Well, itâ€™s not <em>quite</em> as simple as Iâ€™ve shown so far.</p>

<h2>NullableAttribute in more complex scenarios</h2>

<p>It would be oh-so-simple if each parameter or return type could just be nullable or non-nullable. But life gets more complicated than that, with both generics and arrays. Consider a method called <code>GetNames()</code> returning a list of strings. All of these are valid:</p>

<pre class="programlisting">
// Return value is non-null, and elements aren't null
List&lt;string&gt; GetNames()
 
// Return value is non-null, but elements may be null
List&lt;string?&gt; GetNames()
 
// Return value may be null, but elements aren't null
List&lt;string&gt;? GetNames()
 
// Return value may be null, and elements may be null
List&lt;string?&gt;? GetNames()</pre>

<p>So how are those represented in IL? Well, <code>NullableAttribute</code> has one constructor accepting a single <code>byte</code> for simple situations, but another one accepting <code>byte[]</code> for more complex ones like this. Of course, <code>List&lt;string&gt;</code> is still <em>relatively</em> simple â€“ itâ€™s just a single top-level generic type with a single type argument. For a more complex example, imagine <code>Dictionary&lt;List&lt;string?&gt;, string[]?&gt;</code>. (A non-nullable reference to a dictionary where each key is a not-null list of nullable strings, and each value is a possibly-null array of non-nullable elements. Ouch.)</p>

<p>The layout of <code>NullableAttribute</code> in these cases can be thought of in terms of a pre-order traversal of a tree representing the type, where generic type arguments and array element types are leaves in the tree. The above example could be thought of as the tree in Figure 1.</p>

<table class="sidebartable">
	<tr>
		<td><img src="http://accu.org/content/images/journals/ol150/Skeet/Skeet-01.svg" /></td>
	</tr>
	<tr>
		<td class="title">Figure 1</td>
	</tr>
</table>

<p>The pre-order traversal of that tree gives us these values:</p>

<ul>
	<li>Not null (dictionary)</li>
	<li>Not null (list)</li>
	<li>Nullable (string)</li>
	<li>Nullable (array)</li>
	<li>Not null (string)</li>
</ul>

<p>So a parameter declared with that type would be decorated like this:</p>

<pre class="programlisting">
  [Nullable(new byte[] { 1, 1, 2, 2, 1 })]</pre>
  
<p>But wait, thereâ€™s more!</p>

<h2>NullableAttribute in simultaneously-complex-and-simple scenarios</h2>

<p>The compiler has one more trick up its sleeve. When all the elements in the tree are â€˜not nullâ€™ or all elements in the tree are â€˜nullableâ€™, it simply uses the constructor with the single-byte parameter instead. So <code>Dictionary&lt;List&lt;string&gt;, string[]&gt;</code> would be decorated with <code>Nullable[(byte) 1]</code> and <code>Dictionary&lt;List&lt;string?&gt;?, string?[]?&gt;?</code> would be decorated with <code>Nullable[(byte) 2]</code>.</p>

<p>(Admittedly, <code>Dictionary&lt;,&gt;</code> doesnâ€™t permit null keys anyway, but thatâ€™s an implementation detail.)</p>

<h2>Conclusion</h2>

<p>The C# 8 feature of nullable reference types is a really complicated one. I donâ€™t think weâ€™ve seen anything like this since async/await. This article has just touched on one interesting implementation detail. Iâ€™m sure thereâ€™ll be more on nullability over the next few monthsâ€¦</p>

<p class="EditorIntro">This article was first published on Jon Skeetâ€™s coding blog on 10 February 2019 at <a href="https://codeblog.jonskeet.uk/2019/02/10/nullableattribute-and-c-8/">https://codeblog.jonskeet.uk/2019/02/10/nullableattribute-and-c-8/</a></p>

<h2>References</h2>

<p class="bibliomixed"><a id="[Microsoft]"></a>[Microsoft] Background information: <a href="https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/">https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/</a></p>

<p class="bibliomixed"><a id="[NodaTime]"></a>[NodaTime] Alpha build: <a href="https://www.nuget.org/packages/NodaTime/3.0.0-alpha01">https://www.nuget.org/packages/NodaTime/3.0.0-alpha01</a></p>

<p class="bibliomixed"><a id="[Skeet-1]"></a>[Skeet-1] <a href="https://github.com/nodatime/nodatime">https://github.com/nodatime/nodatime</a></p>

<p class="bibliomixed"><a id="[Skeet-2]"></a>[Skeet-2] PR1240: Support nullable reference types, available at: <a href="https://github.com/nodatime/nodatime/pull/1240">https://github.com/nodatime/nodatime/pull/1240</a></p>

<p class="bibliomixed"><a id="[Skeet-3]"></a>[Skeet-3] PR 1264: Use switch expressions, available at:<a href="https://github.com/nodatime/nodatime/pull/1264">https://github.com/nodatime/nodatime/pull/1264</a></p>

<p class="bio"><span class="author"><b>Jon Skeet</b></span> is a Staff Software Engineer at Google, working on making Google Cloud Platform rock for C# developers. Heâ€™s a big C# nerd, enjoying studying the details of language evolution. He is @jonskeet on Twitter, and his email address is on his Stack Overflow profile.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
