C# > Language Features by Version > C# 6 to C# 12 Highlights > Nullable Reference Types (C# 8)
Nullable Reference Types Introduction
This snippet demonstrates the use of nullable reference types, introduced in C# 8, to improve null-safety in your code. It highlights how to enable and utilize nullable reference types to reduce the risk of NullReferenceExceptions.
Enabling Nullable Reference Types
Nullable reference types are disabled by default. To enable them, you need to add the <Nullable>enable</Nullable>
element within a <PropertyGroup>
in your project's .csproj file. This instructs the compiler to treat reference types as non-nullable by default.
<!-- Add this to your .csproj file -->
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Declaring Nullable Reference Types
A non-nullable reference type (string name
) is guaranteed to never be null. The compiler will issue warnings if you try to assign null directly or pass a potentially null value to a non-nullable reference. A nullable reference type (string? nullableName
) can hold either a string value or null. The ?
symbol indicates that the variable is nullable.
string name = "John Doe"; // Non-nullable string
string? nullableName = null; // Nullable string
Checking for Null
Before accessing members of a nullable reference type, you must check if it's null. The compiler will warn you if you access a nullable reference type without a null check. Using an if
statement ensures that you only access the Length
property if nullableName
is not null.
if (nullableName != null)
{
Console.WriteLine("Name: " + nullableName.Length);
}
Suppressing Nullable Warnings
The null-forgiving operator (!
) can be used to suppress nullable warnings. Use this sparingly and only when you are absolutely certain that the variable is not null at that point, even though the compiler can't prove it. Overuse of this operator defeats the purpose of nullable reference types. In this example, even if GetNameFromSomewhere()
can return null, we are telling the compiler that at this specific point maybeNull
is not null, so the compiler will not throw a warning.
string? maybeNull = GetNameFromSomewhere();
string definitelyNotNull = maybeNull!;
Console.WriteLine(definitelyNotNull.Length);
Concepts Behind Nullable Reference Types
The core concept is to differentiate between variables that are designed to be nullable and those that are not. This allows the compiler to help you catch potential NullReferenceExceptions at compile time, rather than runtime. Nullable reference types are a form of static analysis, providing improved code safety. It's important to understand that these are design-time checks; they don't prevent null assignments at runtime if you explicitly bypass the compiler's checks (e.g., using the null-forgiving operator excessively).
Real-Life Use Case
Consider reading configuration data from a file. Some configuration values might be optional, while others are required. Using nullable reference types allows you to clearly indicate which values can be null and forces you to handle potential null values gracefully. Without nullable reference types, you'd have to rely on documentation or conventions, which are prone to errors.
Best Practices
??
(null-coalescing) operator to provide default values when a nullable value is null.
Interview Tip
Be prepared to explain the purpose of nullable reference types and how they improve code safety. Understand the difference between string
and string?
. Know how to enable nullable reference types in a project and how to handle nullable warnings.
When to Use Them
Use nullable reference types in any new C# project and gradually enable them in existing projects. They are especially valuable in large codebases where the risk of NullReferenceExceptions is higher. They help improve the overall quality and maintainability of your code.
Alternatives
Before C# 8, developers relied on coding conventions and code analysis tools to detect potential null-related issues. These approaches were less effective and required more manual effort. Another alternative is defensive programming, which involves adding null checks everywhere, but this can lead to verbose and less readable code.
Pros
Cons
FAQ
-
What happens if I don't enable nullable reference types?
If you don't enable nullable reference types, the compiler will treat all reference types as potentially nullable, but it won't issue warnings if you don't perform null checks. You won't benefit from the improved null-safety features. -
Are nullable reference types a runtime feature?
No, nullable reference types are primarily a compile-time feature. They provide static analysis to help you catch potential null-related issues before runtime. The runtime behavior of reference types remains unchanged. -
Can I disable nullable reference types for specific files?
Yes, you can use pragma directives (#nullable disable
and#nullable restore
) to disable nullable reference types for specific sections of code.