Nullable Reference Types in C#

When C# version 8.0 was introduced in 2019, it came with a bunch of new features and enhancements. One of the newly added features was the Non-Null reference type. Reference types, as you may know, refer to the object that is stored in the heap memory. If the object is no longer “alive” for referencing, the reference type value will be null. .NET treats null as acceptable in most scenarios, but sometimes null values are treated as an illegal value; in those cases, runtime exceptions such as NullReferenceExceptions or ArgumentNullExceptions may be thrown.

Interested in learning C# in a course setting? We have a great list of the Best Online Courses to Learn C# to help get you started.

In this C# programming tutorial, we will learn all about non-null reference types and how to work with them in C# and .NET.

Null reference exceptions are one of the frequently occurring exceptions in .NET applications. In .NET, null references are created with a conviction that reference types can, in some cases, point to null, so it becomes necessary for developers to check those objects explicitly that deal with reference types to ensure that they do not contain null values.

As chances are small that objects are assigned a null value, catching such types of errors can become a difficult task while developing or testing an application; those types of errors are often hidden deep within the codebase. Fortunately for .NET programmers, C# version 8 came up with a solution to fix this problem, courtesy of Nullable reference types.

C# Reference Type Errors

Let’s examine an example of how C# dealt with with null values, prior to the addition of nullable reference types:

string void Main(string[] args){
int notNull = null;  // Compiler warns here
int? yesNull = null;
Nullable num = null;
string text = null;
PassNullReference(text);   // No warning here
}
public static void PassNullReference (string str){
Console.WriteLine(“The first char is ” + str[0]);
}

If you run the above code snippet in your integrated development environment (IDE), you will run into the following exception:

C# Nullable Reference Type

As you can see from the above image, the compiler was only concerned with the integer variable value (int notNull), which is not supposed to hold a null value. It does not, however, worry about the null value, which is passed as an argument in the PassNullReference method. As long as the developer passes a null value to this method, an exception is thrown at runtime. To address this issue, Microsoft introduced the Non-Nullable reference types system.

Read: C# Tools for Code Quality

How to Enable Non-Nullable Reference Types in C#

In C#, the feature of nullable reference types is disabled by default. If developers want to leverage this feature, they need to turn it on manually by adding the following highlighted line of C# code in the of the project file of their project:

How to use C# Non-Nullable Reference Types

Once you enable the Nullable reference types feature, you will see a lot of warnings in Visual Studio or your code editor that indicate that various variables or objects can potentially be null or may return null values.

Example of Non-Nullable Reference Types in C#

Let’s use the same example from our “C# Reference Type Errors” section and make a slight modification to our code to better understand non-nullable references:

string void Main(string[] args){
int noNull = ‘A’;
int? yesNull = null;
string text = null;   // Warning: Converting null literal or possible null value to non-nullable type. 
PassNullReference(text);
}
public static void PassNullReference (string text){
     Console.WriteLine(“The first char is ” + text[0]);
}

You may note here that the compiler does not show any warning in the method definition, but, when you are invoking the method, it does not allow you to pass a null value. It tosses a complaint along the lines of:

Cannot convert null literal to non-nullable reference type.

At this point you might be thinking one solution to this problem may be to add a Null-conditional operator to our reference-type parameter inside the method definition. However, doing so would cause the compiler to toss a different complaint, similar to:

static void Main(string args[]){
PassNullReference(null);
}
public static void PassNullReference (string? text){
Console.WriteLine(“The first char is ” + text[0]); //Warning: Dereference of a possibly null reference
}

This does not mean developers cannot use a reference type as nullable; there are plenty of other techniques programmers can use. One of them is to use the Non-conditional operator. Let’s modify the PassNullReference method so that it returns an integer value rather than void.

static void Main(string args[]){
PassNullReference(null);
}
public static void PassNullReference (string text){
return text.length;
}

If you hover the cursor over the statement PassNullReference(null,) which may be displayed in red underlining in your code editor or IDE, it will show a warning such as:

Cannot convert null literal to non-nullable reference type.

Fortunately, there is a solution to this warning – all you do is add the Elvis operator after the variable ‘text’ and the warning goes away.

static void Main(string[] args)
{
 PassNullReference(null);
}
public static int? PassNullReference(string? text)
{
 return text?.Length;
}

So far, we have seen how we can avoid bugs in our programs by leveraging Non-Nullable reference types. The compiler reminds programmers by issuing warnings that you should be very careful dealing with code that uses nullable references.

Non-Nullable References and Classes in C#

In the next portion of our programming tutorial, we will look at how Non-nullable reference types work with classes in C#.

Let’s create a class called Book with two properties: Id and BookName.

public class Book
{
public int Id { get;set; }
public string BookName { get;set; }
}

The compiler may issue a warning here, and, if you have enabled the ‘Treat Warnings as Errors’ option to true in your code editor, it will prevent you from running the code.

You might be thinking you can use our previous solution to solve this problem (meaning use the Null-conditional operator). You would, in fact, be correct. In addition, you need to make sure when instantiating the Book class that you do not pass null to the constructor. Also, make sure that the property ‘BookName’ is not null. Doing this will ensure the compiler helps you to be in check with your referencing or dereferencing of code:

public class Book
{
public int Id { get;set; }
public string? BookName { get;set; }
}

In some instances the compiler may not be sure if you are validating null values or not. Let’s understand this scenario better by adding a method to our class, as shown in the code below:

public static string GetBookGenre(bool isFiction)
{
 	return isFiction? "Not null" : null;
}

The compiler, in this case, is not certain whether you are returning a non-nullable reference or not, so it sends a warning. A solution to this problem is to just put a Null-conditional operator in the method’s signature:

public static string? GetBookGenre (bool isFiction)
{
 	return isFiction? "Not null" : null;
}

Non-Nullable Reference Types and Generics in C#

C# version 8.0 and beyond allows you to add a new generic constraint that will make sure that the generic parameter you are passing can never be null. Consider the following code snippet:

public static void MyMethod()
 where TParam: notnull
{
}

Notice we have added the TParam: notnull constraint, which means you would not be able to call the method with a nullable parameter:

static void Main(string[] args)
{
 	MyMethod ();   // a valid call
}

In the above scenario, MyMethod () would be a valid call.

Final Thoughts on Non-Nullable Reference Types in C#

In this programming tutorial, we showcased the simplicity of Non-Nullable reference types in C#, beginning with version 8. We recommend you try this feature out in a small-size application and see how being explicit about your code’s behavior is helpful in figuring out defects in your code and programming logic.

Read more C# programming tutorials.

Tariq Siddiqui
Tariq Siddiqui
A graduate in MS Computer Applications and a Web Developer from India with diverse skills across multiple Web development technologies. Enjoys writing about any tech topic, including programming, algorithms and cloud computing. Traveling and playing video games are the hobbies that interest me most.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read