This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.

Title

Upgrading to nullability in C#

Description

<img attachment="interrobang.jpg" align="right">The <a href="https://blog.maartenballiauw.be/talk/2024/01/21/bringing-csharp-nullability-into-existing-code.html" author="Maarten Balliauw">Talk - Bringing C# nullability into existing code</a> is a 66-slide deck that I summarize as follows: <ul> The C# nullability feature is for build- and design-time. It does not enforce anything at runtime. That means that you still have to check parameters for <c>null</c>. The C# nullability feature is available to solutions working with .NET Framework and .NET. For .NET Framework, you have to explicitly set the <c><languageversion></c> to <c>8.0</c> (however, there are a bunch of cons associated with doing this, as the runtime library itself is not annotated).<fn> The presentation shows how to enable and disable for the whole solution, project, or an individual code region. For new solutions, enable at the solution level. For small solutions, enable at the solution level and just work through it. For large solutions, enable project-by-project or file-by-file---or even class-by-class.<ul> <iq>Start at the center and work outwards.</iq> While <c>?</c> suffices in most cases, consider annotations to improve your own APIs Consider redesigning APIs that return <c>null</c> (use the <c>bool TryGet<t>(..., out T)</c> pattern or return a "null" object instead). Avoid allowing <c>null</c> parameters (these force a decision on the implementation that is often better handled by the caller). Don't use <c>!</c> except temporarily Don't use suppression except temporarily Start with types that aren't depended on a lot. Those are easy. Take types with lots of dependents one-by-one. </ul> </ul> <hr> <ft>For more information, see <a href="https://endjin.com/blog/2020/07/dotnet-csharp-8-nullable-references-supporting-older-runtimes" author="Ian Griffiths">C# 8.0 nullable references: supporting older runtimes</a>, published in July of 2021. Also, the article <a href="https://medium.com/@joni2nja/consider-using-c-8-with-the-net-framework-9dceb20647c5">Consider using C# 8 with the .NET Framework</a> cites from <a href="https://devblogs.microsoft.com/dotnet/building-c-8-0/">Building C# 8.0</a> by Mads Torgersen. Both of those articles are from 2018. <bq>using C# 8.0 is only supported on platforms that implement .NET Standard 2.1</bq> .NET Framework doesn't implement .NET Standard 2.1 However, the StackOverflow post <a href="https://stackoverflow.com/questions/56651472/does-c-sharp-8-support-the-net-framework">Does C# 8 support the .NET Framework?</a> goes into some detail about <i>which</i> features of C# 8.0 <i>could</i> be supported under .NET Framework. That post notes that <i>syntax-only</i> changes will continue to work, which makes sense. As long as you use a newer compiler that understands the syntax, the lowered code and subsequent generated IL will be compatible with the .NET Framework runtime. That's what syntax-only means: no new functionality was required in the runtime in order to support the generated output. <ul> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#static-local-functions">Static local functions</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations">Using declarations</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#null-coalescing-assignment">Null-coalescing assignment</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#readonly-members">Readonly members</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#disposable-ref-structs">Disposable ref structs</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#positional-patterns">Positional patterns</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#tuple-patterns">Tuple patterns</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#switch-expressions">Switch expressions</a> <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#nullable-reference-types">Nullable reference types</a> are also supported, but the new <a href="http://learn.microsoft.com/en-us/dotnet/csharp/nullable-attributes">nullable attributes</a> required to design the more complex nullable use cases are not. However, according to <a href="https://endjin.com/blog/2020/07/dotnet-csharp-8-nullable-references-supporting-older-runtimes) (from July 2020">C# 8.0 nullable references: supporting older runtimes</a>, there's a <a href="https://www.nuget.org/packages/Nullable/">Nullable Nuget package</a>. Be aware, though, that the .NET Framework is not itself annotated, so you will probably see spurious warnings when the compiler can't tell that a result can never be null. </ul> That's a lot of features, actually! The StackOverflow post linked above lists them quite well, and <a href="https://stu.dev/csharp8-doing-unsupported-things/">C# 8.0 and .NET Standard 2.0 - Doing Unsupported Things</a> has some more information about which level of change each C# 8.0 feature requires. That said, <bq>The C# 8/.NET Framework combination is not officially supported by Microsoft. It is, they say, for experts only.</bq></ft>