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?
If "Key"
isn't found in the dictionary, then a value of null
will be assigned to the value
variable. However you've declared value
as string
, meaning that it shouldn't contain null
. Therefore the compiler is giving you a warning.
The fact that you've initially assigned string.Empty
to value
doesn't matter - that will always get overwritten by TryGetValue
(and you should get another warning which says that).
You should declare value
as a string?
, to indicate that its value might be null
.
Note that the compiler's pretty smart. If you write:
if (!dictionary.TryGetValue("Key", out string? value))
{
value = string.Empty;
}
then the compiler knows that value
cannot be null
, and it won't complain if you then try and call methods on it.
canton7's answer is correct (+1).
This is not an explanation but a workaround:
You could add an extension method to Dictionary<TVey, TValue>
like this:
public static bool TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue @default, out TValue @value) where TKey : notnull
{
var result = dictionary.TryGetValue(key, out var val);
@value = result ? val : @default;
return result;
}
Then you can use it like this:
private static void Method()
{
var dictionary = new Dictionary<string, string>();
/// populate dictionary here...
dictionary.TryGetValue("Key", string.Empty, out var value);
}
This should enable you to keep value
as a non-nullable string.
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.