可空引用类型:"Try" 方法模式,返回 false 时收到 null 警告
Nullable reference types: "Try" method pattern, getting warning for null when returning false
我有以下使用“尝试”模式的方法。
public bool TryGetValue(string subnet, [NotNullWhen(true)] out TValue value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default;
return false;
}
在线 value = default
- 我收到编译器警告 CS8601:“可能的空引用赋值”。下一行 returns false
和 value
具有 [NotNullWhen(true)]
属性。
我是不是遗漏了什么,或者编译器是否出于某种原因没有携带 value
的状态?
完整示例 sharplab.io and a Github gist
您可以看看类似的方法,例如 Dictionary<TKey, TValue>.TryGetValue
, are implemented in .NET Core. In your case you should use null-forgiving operator !
是如何抑制警告的(因为 TValue
声明为不可空类型)
value = default!;
return false;
(以下答案适用于 Visual Studio 16.6/.NET Core 3.1)
在这种情况下,您应该使用 [MaybeNullWhen(false)]
而不是 [NotNullWhen(true)]
。
public bool TryGetValue(string subnet, [MaybeNullWhen(false)] out TValue value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default;
return false;
}
解释:
要理解的关键点是应用 [NotNullWhen(true)]
属性并不意味着 [MaybeNullWhen(false)]
.
在您的示例中,允许提供不可为 null 的引用类型,例如 string
作为 TValue
的类型参数。这将产生以下方法:
public bool TryGetValue(string subnet, [NotNullWhen(true)] out string value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default; // Wait, default(string) is null! We can't do this!
return false;
}
您可能想要做的不是告诉调用者该方法将 return“为真时不为空”,而是告诉他们“在为假时可能 return 为空”。然后,包含类型 TreeNode<TValue>
的 类型参数 将告知调用者是否应该在该方法 return 为真时期望非空 value
。因此实例化看起来像:
public bool TryGetValue(string subnet, [MaybeNullWhen(false)] out string value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default; // ok
return false;
}
因为赋值的目标有MaybeNullWhen
,编译器允许你给它赋值null。我们只需在您的 return 语句中检查变量的空状态是否与 return 值兼容。例如,如果我们将上面的 return false
更改为 return true
,您将收到可空性警告。
我有以下使用“尝试”模式的方法。
public bool TryGetValue(string subnet, [NotNullWhen(true)] out TValue value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default;
return false;
}
在线 value = default
- 我收到编译器警告 CS8601:“可能的空引用赋值”。下一行 returns false
和 value
具有 [NotNullWhen(true)]
属性。
我是不是遗漏了什么,或者编译器是否出于某种原因没有携带 value
的状态?
完整示例 sharplab.io and a Github gist
您可以看看类似的方法,例如 Dictionary<TKey, TValue>.TryGetValue
, are implemented in .NET Core. In your case you should use null-forgiving operator !
是如何抑制警告的(因为 TValue
声明为不可空类型)
value = default!;
return false;
(以下答案适用于 Visual Studio 16.6/.NET Core 3.1)
在这种情况下,您应该使用 [MaybeNullWhen(false)]
而不是 [NotNullWhen(true)]
。
public bool TryGetValue(string subnet, [MaybeNullWhen(false)] out TValue value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default;
return false;
}
解释:
要理解的关键点是应用 [NotNullWhen(true)]
属性并不意味着 [MaybeNullWhen(false)]
.
在您的示例中,允许提供不可为 null 的引用类型,例如 string
作为 TValue
的类型参数。这将产生以下方法:
public bool TryGetValue(string subnet, [NotNullWhen(true)] out string value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default; // Wait, default(string) is null! We can't do this!
return false;
}
您可能想要做的不是告诉调用者该方法将 return“为真时不为空”,而是告诉他们“在为假时可能 return 为空”。然后,包含类型 TreeNode<TValue>
的 类型参数 将告知调用者是否应该在该方法 return 为真时期望非空 value
。因此实例化看起来像:
public bool TryGetValue(string subnet, [MaybeNullWhen(false)] out string value)
{
if (!TryFindNode(subnet, out var node))
throw new InvalidOperationException();
if (TValueIsDefault(node.Value) == false)
{
value = node.Value;
return true;
}
value = default; // ok
return false;
}
因为赋值的目标有MaybeNullWhen
,编译器允许你给它赋值null。我们只需在您的 return 语句中检查变量的空状态是否与 return 值兼容。例如,如果我们将上面的 return false
更改为 return true
,您将收到可空性警告。