在处理不可为空类型的空值的 setter 上停止 C# 警告“可能的空引用分配”

use*_*758 3 c# null compiler-warnings

public class Example
{
    public string Name
    {
        get => m_name;
        set => m_name = value ?? string.Empty; // valid to assign null cause it's handled but caused warnings
    }
    private string m_name;

    public Example(string? name)
    {
        Name = name; // CS8601 - Possible null reference assignment.
    }
}

// imagine this is setting on an instance and not the type
Example.Name = data; // CS8601 - Possible null reference assignment.
Run Code Online (Sandbox Code Playgroud)

在代码中,我有一个string永远不为空的类型,因为属性设置器将空赋值转换为默认值。编译器不理解这一点并且对此抱怨不已。

我知道我可以通过以下方式修复其中一些问题:

  • 放在!赋值之后,因为我比编译器更了解 - 不喜欢这样,因为它可能会因重构而中断
  • 在构造函数中分配支持字段而不是属性 - 可以工作,但会重复构造函数中的后备代码,并且再次意味着如果重构/更改,则必须更新多个位置
  • Name将类型更改为string?- 在这些情况下有效,但会向尝试获取值的所有位置添加编译器警告,这可能不仅仅是设置属性!

有没有一种方法可以解决这个警告而不是hacky?

例如,告诉 setter 可以进行赋值,或者添加与可在方法上使用的null样式相同的属性?[MaybeNullWhen(false)]TryGet

我找不到不涉及代码重复或忽略编译器的问题的解决方法

Swe*_*per 6

这是 的用例AllowNullAttribute这里的文档显示了非常相似的情况。

你只需要做:

using System.Diagnostics.CodeAnalysis;

// ...

[AllowNull]
public string Name
{
    get => m_name;
    set => m_name = value ?? string.Empty;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以为此属性分配可为空的类型。

如果您要在构造函数中设置属性而不是字段,则还应该标记 setter ,MemberNotNullAttribute以便静态分析器可以看到您已经初始化了构造函数中的所有不可空字段。

[MemberNotNull("m_name")]
set => m_name = value ?? string.Empty;
Run Code Online (Sandbox Code Playgroud)