Other instances when you get these warnings may be false positive. You may have a private utility method that tests for null. The compiler doesn't know that the method provides a null check. Consider the following example that uses a private utility method,
IsNotNull
:
public void WriteMessage(string? message)
if (IsNotNull(message))
Console.WriteLine(message.Length);
The compiler warns that you may be dereferencing null when you write the property
message.Length
because its static analysis determines that
message
may be
null
. You may know that
IsNotNull
provides a null check, and when it returns
true
, the
null-state
of
message
should be
not-null
. You must tell the compiler those facts. One way is to use the null forgiving operator,
!
. You can change the
WriteLine
statement to match the following code:
Console.WriteLine(message!.Length);
The null forgiving operator makes the expression not-null even if it was maybe-null without the !
applied. In this example, a better solution is to add an attribute to the signature of IsNotNull
:
private static bool IsNotNull([NotNullWhen(true)] object? obj) => obj != null;
The System.Diagnostics.CodeAnalysis.NotNullWhenAttribute informs the compiler that the argument used for the obj
parameter is not-null when the method returns true
. When the method returns false
, the argument has the same null-state it had before the method was called.
There's a rich set of attributes you can use to describe how your methods and properties affect null-state. You can learn about them in the language reference article on Nullable static analysis attributes.
Fixing a warning for dereferencing a maybe-null variable involves one of three techniques:
Add a missing null check.
Add null analysis attributes on APIs to affect the compiler's null-state static analysis. These attributes inform the compiler when a return value or argument should be maybe-null or not-null after calling the method.
Apply the null forgiving operator !
to the expression to force the state to not-null.
Possible null assigned to a nonnullable reference
This set of warnings alerts you that you're assigning a variable whose type is nonnullable to an expression whose null-state is maybe-null. These warnings are:
CS8597 - Thrown value may be null.
CS8600 - Converting null literal or possible null value to non-nullable type.
CS8601 - Possible null reference assignment.
CS8603 - Possible null reference return.
CS8604 - Possible null reference argument for parameter.
CS8605 - Unboxing a possibly null value.
CS8625 - Cannot convert null literal to non-nullable reference type.
CS8629 - Nullable value type may be null.
The compiler emits these warnings when you attempt to assign an expression that is maybe-null to a variable that is nonnullable. For example:
string? TryGetMessage(int id) => "";
string msg = TryGetMessage(42); // Possible null assignment.
The different warnings indicate provide details about the code, such as assignment, unboxing assignment, return statements, arguments to methods, and throw expressions.
You can take one of three actions to address these warnings. One is to add the ?
annotation to make the variable a nullable reference type. That change may cause other warnings. Changing a variable from a non-nullable reference to a nullable reference changes its default null-state from not-null to maybe-null. The compiler's static analysis may find instances where you dereference a variable that is maybe-null.
The other actions instruct the compiler that the right-hand-side of the assignment is not-null. The expression on the right-hand-side could be null-checked before assignment, as shown in the following example:
string notNullMsg = TryGetMessage(42) ?? "Unknown message id: 42";
The previous examples demonstrate assignment of the return value of a method. You may annotate the method (or property) to indicate when a method returns a not-null value. The System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute often specifies that a return value is not-null when an input argument is not-null. Another alternative is to add the null forgiving operator, !
to the right-hand side:
string msg = TryGetMessage(42)!;
Fixing a warning for assigning a maybe-null expression to a not-null variable involves one of four techniques:
Change the left side of the assignment to a nullable type. This action may introduce new warnings when you dereference that variable.
Provide a null-check before the assignment.
Annotate the API that produces the right-hand side of the assignment.
Add the null forgiving operator to the right-hand side of the assignment.
Nonnullable reference not initialized
This set of warnings alerts you that you're assigning a variable whose type is non-nullable to an expression whose null-state is maybe-null. These warnings are:
CS8618 - Non-nullable variable must contain a non-null value when exiting constructor. Consider declaring it as nullable.
CS8762 - Parameter must have a non-null value when exiting.
Consider the following class as an example:
public class Person
public string FirstName { get; set; }
public string LastName { get; set; }
Neither FirstName
nor LastName
are guaranteed initialized. If this code is new, consider changing the public interface. The above example could be updated as follows:
public class Person
public Person(string first, string last)
FirstName = first;
LastName = last;
public string FirstName { get; set; }
public string LastName { get; set; }
If you require creating a Person
object before setting the name, you can initialize the properties using a default non-null value:
public class Person
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
Another alternative may be to change those members to nullable reference types. The Person
class could be defined as follows if null
should be allowed for the name:
public class Person
public string? FirstName { get; set; }
public string? LastName { get; set; }
Existing code may require other changes to inform the compiler about the null semantics for those members. You may have created multiple constructors, and your class may have a private helper method that initializes one or more members. You can move the initialization code into a single constructor and ensure all constructors call the one with the common initialization code. Or, you can use the System.Diagnostics.CodeAnalysis.MemberNotNullAttribute and System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute attributes. These attributes inform the compiler that a member is not-null after the method has been called. The following code shows an example of each. The Person
class uses a common constructor called by all other constructors. The Student
class has a helper method annotated with the System.Diagnostics.CodeAnalysis.MemberNotNullAttribute attribute:
using System.Diagnostics.CodeAnalysis;
public class Person
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string firstName, string lastName)
FirstName = firstName;
LastName = lastName;
public Person() : this("John", "Doe") { }
public class Student : Person
public string Major { get; set; }
public Student(string firstName, string lastName, string major)
: base(firstName, lastName)
SetMajor(major);
public Student(string firstName, string lastName) :
base(firstName, lastName)
SetMajor();
public Student()
SetMajor();
[MemberNotNull(nameof(Major))]
private void SetMajor(string? major = default)
Major = major ?? "Undeclared";
Finally, you can use the null forgiving operator to indicate that a member is initialized in other code. For another example, consider the following classes representing an Entity Framework Core model:
public class TodoItem
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public class TodoContext : DbContext
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
public DbSet<TodoItem> TodoItems { get; set; } = null!;
The DbSet
property is initialized to null!
. That tells the compiler that the property is set to a not-null value. In fact, the base DbContext
performs the initialization of the set. The compiler's static analysis doesn't pick that up. For more information on working with nullable reference types and Entity Framework Core, see the article on Working with Nullable Reference Types in EF Core.
Fixing a warning for not initializing a nonnullable member involves one of four techniques:
Change the constructors or field initializers to ensure all nonnullable members are initialized.
Change one or more members to be nullable types.
Annotate any helper methods to indicate which members are assigned.
Add an initializer to null!
to indicate that the member is initialized in other code.
Mismatch in nullability declaration
Many warnings indicate nullability mismatches between signatures for methods, delegates, or type parameters.
CS8608 - Nullability of reference types in type doesn't match overridden member.
CS8609 - Nullability of reference types in return type doesn't match overridden member.
CS8610 - Nullability of reference types in type parameter doesn't match overridden member.
CS8611 - Nullability of reference types in type parameter doesn't match partial method declaration.
CS8612 - Nullability of reference types in type doesn't match implicitly implemented member.
CS8613 - Nullability of reference types in return type doesn't match implicitly implemented member.
CS8614 - Nullability of reference types in type of parameter doesn't match implicitly implemented member.
CS8615 - Nullability of reference types in type doesn't match implemented member.
CS8616 - Nullability of reference types in return type doesn't match implemented member.
CS8617 - Nullability of reference types in type of parameter doesn't match implemented member.
CS8619 - Nullability of reference types in value doesn't match target type.
CS8620 - Argument cannot be used for parameter due to differences in the nullability of reference types.
CS8621 - Nullability of reference types in return type doesn't match the target delegate (possibly because of nullability attributes).
CS8622 - Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).
CS8624 - Argument cannot be used as an output due to differences in the nullability of reference types.
CS8631 - The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type.
CS8633 - Nullability in constraints for type parameter of method doesn't match the constraints for type parameter of interface method. Consider using an explicit interface implementation instead.
CS8634 - The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.
CS8643 - Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type.
CS8644 - Type does not implement interface member. Nullability of reference types in interface implemented by the base type doesn't match.
CS8645 - Member is already listed in the interface list on type with different nullability of reference types.
CS8667 - Partial method declarations have inconsistent nullability in constraints for type parameter.
CS8714 - The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint.
CS8764 - Nullability of return type doesn't match overridden member (possibly because of nullability attributes).
CS8765 - Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
CS8766 - Nullability of reference types in return type of doesn't match implicitly implemented member (possibly because of nullability attributes).
CS8767 - Nullability of reference types in type of parameter of doesn't match implicitly implemented member (possibly because of nullability attributes).
CS8768 - Nullability of reference types in return type doesn't match implemented member (possibly because of nullability attributes).
CS8769 - Nullability of reference types in type of parameter doesn't match implemented member (possibly because of nullability attributes).
CS8819 - Nullability of reference types in return type doesn't match partial method declaration.
The following code demonstrates CS8764:
public class B
public virtual string GetMessage(string id) => string.Empty;
public class D : B
public override string? GetMessage(string? id) => default;
The preceding example shows a virtual
method in a base class and an override
with different nullability. The base class returns a non-nullable string, but the derived class returns a nullable string. If the string
and string?
are reversed, it would be allowed because the derived class is more restrictive. Similarly, parameter declarations should match. Parameters in the override method can allow null even when the base class doesn't.
Other situations can generate these warnings. You may have a mismatch in an interface method declaration and the implementation of that method. Or a delegate type and the expression for that delegate may differ. A type parameter and the type argument may differ in nullability.
To fix these warnings, update the appropriate declaration.
Code doesn't match attribute declaration
The preceding sections have discussed how you can use Attributes for nullable static analysis to inform the compiler about the null semantics of your code. The compiler warns you if the code doesn't adhere to the promises of that attribute:
CS8607 - A possible null value may not be used for a type marked with [NotNull]
or [DisallowNull]
CS8763 - A method marked [DoesNotReturn]
should not return.
CS8770 - Method lacks [DoesNotReturn]
annotation to match implemented or overridden member.
CS8774 - Member must have a non-null value when exiting.
CS8775 - Member must have a non-null value when exiting.
CS8776 - Member cannot be used in this attribute.
CS8777 - Parameter must have a non-null value when exiting.
CS8824 - Parameter must have a non-null value when exiting because parameter is non-null.
CS8825 - Return value must be non-null because parameter is non-null.
Consider the following method:
public bool TryGetMessage(int id, [NotNullWhen(true)] out string? message)
message = null;
return true;
The compiler produces a warning because the message
parameter is assigned null
and the method returns true
. The NotNullWhen
attribute indicates that shouldn't happen.
To address these warnings, update your code so it matches the expectations of the attributes you've applied. You may change the attributes, or the algorithm.
Exhaustive switch expression
Switch expressions must be exhaustive, meaning that all input values must be handled. Even for non-nullable reference types, the null
value must be accounted for. The compiler issues warnings when the null value isn't handled:
CS8655 - The switch expression does not handle some null inputs (it is not exhaustive).
CS8847 - The switch expression does not handle some null inputs (it is not exhaustive). However, a pattern with a 'when' clause might successfully match this value.
The following example code demonstrates this condition:
int AsScale(string status) =>
status switch
"Red" => 0,
"Yellow" => 5,
"Green" => 10,
{ } => -1
The input expression is a string
, not a string?
. The compiler still generates this warning. The { }
pattern handles all non-null values, but doesn't match null
. To address these errors, you can either add an explicit null
case, or replace the { }
with the _
(discard) pattern. The discard pattern matches null as well as any other value.