我可以告诉C#可为空的引用方法实际上是对字段的空检查吗


14

考虑以下代码:

#nullable enable
class Foo
{
    public string? Name { get; set; }
    public bool HasName => Name != null;
    public void NameToUpperCase()
    {
        if (HasName)
        {
            Name = Name.ToUpper();
        }
    }
}

在Name = Name.ToUpper()上,我收到一条警告,指出Name是可能的空引用,这显然是错误的。我可以通过内联HasName来解决此警告,因此条件是if(Name!= null)。

有什么方法可以指示编译器,HasName的真实响应暗含对Name的不可为空性的约束?

这很重要,因为HasName实际上可能会测试更多的东西,并且我可能想在多个地方使用它,或者它可能是API表面的公共部分。有很多原因希望将空检查纳入其自己的方法中,但是这样做似乎破坏了可空引用检查器。


1
您应该HasValue在可为null的类型上使用IMO ,而不要针对进行检查null。不过,这可能不会影响您的问题。
fredrik '19

我想你时,你可以用你的代码与#nullable disable#nullable enablerestore再之后(docs.microsoft.com/en-us/dotnet/csharp/...)。
GaryNg

5
您可以使用“ dammit” !运算符。if(HasName) { Name = Name!.ToUpper(); }
Jan Paolo

1
对于多线程应用程序,您可以在HasName检查之后将Name设置为null,在本地使用变量而不是返回属性(该属性知道其属性在其吸气剂中的作用)会产生一些时髦的错误(记住使用事件处理程序的地方很多)
XIU

Answers:


3

我环顾了与的不同属性,System.Diagnostics.CodeAnalysis找不到任何适用的属性,这非常令人失望。您所能找到的最接近的是:

public bool TryGetName([NotNullWhen(true)] out string? name)
{
    name = Name;
    return name != null;
}

public void NameToUpperCase()
{
    if (TryGetName(out var name))
    {
        Name = name.ToUpper();
    }
}

我知道这看起来很麻烦。您可以在MSDN文档中查看可为空的属性,也许您会发现更整洁的东西。


2
似乎我们需要更多属性或类似打字稿的断言
Stilgar

我选择这个作为答案,因为正如我担心的那样,真正的答案似乎是“不,C#尚未这样做”。
约翰·梅尔维尔,

@JohnMelville我也无法找到有关此功能的建议,因此我认为我们不能指望这种情况会很快改变。
V0ldek '19

2
@XIU编译器在这方面已经松懈。如果这样做if(Name != null) return Null.ToUpper(),即使从技术上说这是TOCTOU竞争条件,也不会警告取消空引用。我记得Mads Torgersen谈到了他们的看法,但是它会产生如此多的误报,整个可为空的引用类型功能实际上将是无用的-99%的时间您的属性不会被另一个线程更改。因此,您要做的就是创建一个属性,该属性将使对该属性的检查被视为对另一个属性的null检查。
V0ldek

2
我解决了“无法为此找到建议”的问题。(github.com/dotnet/csharplang/issues/2997)祝我好运。
约翰·梅尔维尔,

-10

字符串是引用类型,可int?空值(例如)是可空值类型。所以你真的不能这样做string? myString; 您需要的是:

class Foo
{
    public string Name { get; set; }
    public bool HasName => !String.IsNullOrEmpty(Name);  ////assume you want empty to be treated same way as null
    public void NameToUpperCase()
    {
        if (HasName)
        {
            Name = Name.ToUpper();
        }
    }
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.