How many times do you find yourself testing a C# code but you get NullReferenceException
because you didn't instantiate an object correctly or you didn't have your null checks set right? It is something that we deal with frequently, but this will change with the "nullable reference types" introduced in C# 8 and enabled by default in C# 10 & .Net 6.
There are enough resources on this subject. This is a quick article to explain the reasoning behind this feature and how you would leverage it in real life.
If you don't know what reference types are, you can check my article about C# memory management and garbage collection. Make sure to check the official C# Nullable Reference documentation.
Explaining Nullable Reference Types
Before C# 7, only value types can be defined as nullable
Int a;
Int? b;
"?" means that b is an int and can be null. a
is equal to 0 by default even if not assigned a value.
Reference types can take null as a value without using "?". If you write, string? text;
The compiler will throw an error.
Using Nullable Reference Types
Nullable reference types are introduced in C# 8 and enabled by default in C# 10.
Declaring reference types as usual
If you declare your reference types as usual, you will see new warnings telling you that you didn't make sure to assign default values or you didn't initialize them correctly in the constructor as if the variable is not intended to be null.
Declaring reference types as nullable using "?"
In this case, you will get different warnings telling you that you are dereferencing a null variable. When you provide the right null checks, these warnings go away. In this case, the compiler is doing the heavy lifting by analyzing the code.
What if the compiler is not able to find out that your variable cannot be null and proceeds to warn you that you are dereferencing a null variable, in this case, you can use the null-forgiving-operator "!" like in the example below.
namespace NullableReferences;
public class User
{
public string Name { get; set; }
public string Email { get; set; }
}
public static class Program
{
public static void Run(string?[] args)
{
User user;
if (args.Length == 2)
user = new User(){Name = args[0]!, Email = args[1]!};
}
}
To summarize, whether you declare reference types as nullable or not, you will see new warnings while working with C# 10. This can be annoying when migrating a large C# code base to C#10.
Fortunately, this feature is configurable as stated in the codebase migration guide. You can use the tag <nullable>
in the .csproj file to provide one of these values:
Enable: Enables this feature, you should update the code to use nullable reference types accordingly and resolve all warnings. A good choice for a small code base.
Disable: Disable this feature, and you continue writing code as with previous C# versions without any work needed. Such code is considered a nullable oblivious code.
Warnings: can be activated for a two-phase migration process which will be a good approach for large codebases.
<nullable>warnings</warnings>
will generate warnings when a potentially null reference type is dereferenced and you can declare nullable references using"?"
. However, you can use annotations#nullable enable
and#nullable disable
to enable or disable this feature for each file separately as you update the code little by little. Nullable is disabled by default if the file doesn't include the annotation.Annotations: No warnings are generated but you can still declare nullable reference types with
"?"
, you use the same annotations mentioned above to migrate the code little by little.
You can check the table that summarizes the Nullable Context options.
I hope you found this article helpful. Feel free to leave a comment or a reaction and consider subscribing to the newsletter to receive my upcoming articles.