I modified my csproj
file to enable null reference types in C#8:
<Nullable>enable</Nullable>
Given the following code:
private static void Method()
{
var dictionary = new Dictionary<string, string>();
string value = string.Empty;
dictionary.TryGetValue("Key", out value);
}
The line with TryGetValue()
gives the warning:
CS8600
: Converting null literal or possible null value to non-nullable type.
I don't understand why. The signature of TryGetValue()
is :
public bool TryGetValue(string key, [MaybeNullWhen(false)] out string value);
The code example has only non-nullable references. Why is it getting this error?
From the documentation Attributes for null-state static analysis interpreted by the C# compiler.
In a nullable enabled context, the compiler performs static analysis of code to determine the null-state of all reference type variables:
- not-null: Static analysis determines that a variable has a non-null value.
- maybe-null: Static analysis can't determine that a variable is assigned a non-null value.
The static analyzer consider a variable can be :
When a not nullable variable is decorated with the attribute MaybeNull, the static analyser consider the variable is maybe nullable.
[return: MaybeNull]
static string Find(string key)
{
return key == "" ? null : key;
}
string value1 = Find("key"); // Warning CS8600 Converting null literal or possible null value to non-nullable type.
string? value2 = Find("key"); // No warning
var value3 = Find("key"); // The inferred type is 'string?'
The MaybeNullWhen attribute is similar, but the static analyser can handle checks based on the result of the method.
static bool TryGetValue(string key, [MaybeNullWhen(false)] out string value)
{
if(key == "")
{
value = null;
return false;
}
value = "Foo";
return true;
}
string notnullable;
string value1;
if (TryGetValue("Key", out value1)) // Warning CS8600 Converting null literal or possible null value to non-nullable type.
notnullable = value1;
else
notnullable = value1; // Warning CS8600 Converting null literal or possible null value to non-nullable type.
string? value2;
if (TryGetValue("Key", out value2))
notnullable = value2;
else
notnullable = value2; // Warning CS8600 Converting null literal or possible null value to non-nullable type.
I agree, that makes no sense in this examples. But with a generic method, you can specify a non nullable type while the method can return/set null:
[return: MaybeNull]
static T Find<T>(string key);
static bool TryGetValue<T>(string key, [MaybeNullWhen(false)] out T value)