MaybeNull 属性对空引用发出警告 return

MaybeNull attribute warns on null reference return

作为转向 C# 8 可空引用类型的一部分,我遇到了以下代码(已简化):

public string GetIfExists(string key)
{
    dict.TryGetValue(key, out var value);

    return value;
}

return 行对可能的空引用 return 发出警告,这是有道理的。所以我尝试用 [return: MaybeNull] 属性注释该方法,但警告仍然出乎我的意料。从 documentation,我了解到此属性将 return 类型标记为可选 null,即使实际类型不允许。

似乎我避免警告的唯一选择是标记 return 类型 string?。那么[return: MaybeNull]有什么用呢?

来自文档:

[return: MaybeNull] informs callers that the contract implies a non-nullable type, but the return value may actually be null. Use the MaybeNull attribute when your API should be a non-nullable type, typically a generic type parameter, but there may be instances where null would be returned.

这意味着您希望在不更改合同的情况下显示警告时使用该属性。

似乎已创建属性以帮助在两种情况下强制执行不可为空性(传播强制用户检查是否为 null 的警告):

  • 在无法更改函数签名的情况下。
  • 在涉及泛型的情况下。泛型,由于它们的性质,有点难以处理,您可能会发现自己处于不允许使用 T? 的情况,但您仍然希望该方法的用户知道结果需要检查。

消除警告的唯一方法是将 return 类型更改为 string?(或 return value!;,但这是一个谎言 :p)。

您的问题无法重现。

public string GetIfExists ( string key )
{
  new Dictionary<string, string>().TryGetValue (key, out string value); // Warning  CS8600  Converting null literal or possible null value to non-nullable type.
  return value; // Warning  CS8603  Possible null reference return.
}
[return: MaybeNull]
public string GetIfExists ( string key )
{
  new Dictionary<string, string>().TryGetValue (key, out string? value);
  return value;
}

(没问题‼)


从泛型的使用角度来看,T? return type[return: MaybeNull]. 之间没有区别(也适用于 reference type.)

[return: MaybeNull]
public T Find<T> ( ) => default;
public T? Find2<T> () => default;    
public T Find3<T> ( ) => default;  // Warning   CS8603  Possible null reference return.

void Test ()
{
  object x = Find<object> (); // Warning    CS8600  Converting null literal or possible null value to non-nullable type.
  object x2 = Find2<object> (); // Warning  CS8600  Converting null literal or possible null value to non-nullable type.
  object x3 = Find3<object> ();
}