这是一个启用了可为空引用类型的示例C#程序

这是一个启用了可为空引用类型的示例 C# 程序:

using System;
using System.Collections.Generic;
using System.Linq;
MyStruct myStruct = new("A");
List list = new() { myStruct };
MyStruct found = list.FirstOrDefault(item => item.Str == "B");
Console.WriteLine(found.Str.Length);
struct MyStruct
{
    public readonly string Str;
    public MyStruct(string str)
    {
        Str = str;
    }
}

注意MyStruct 包含一个不可为空 Str 字段。 理论上这意味着Str 字段永远不应该为空,并且编译器在几乎所有情况下都会警告你如果你让它为空。

然而,空值可能会出现的一种情况是,如果通过通用方法返回未初始化的结构,例如上面的 FirstOrDefault 调用。在这种情况下,Str 字段 为 null,但 C# 编译器在访问 Str 或分配 found 变量时不会给出警告,因此程序会因NullReferenceException 尝试访问 found.Str.Length 时。 (另一种情况,如果从数组中读取结构。)

更糟糕的是,一些代码分析工具会错误地警告反对检查以确保found.Str 不为空。 (例如,如果我添加 if(found.Str != null),那么 Resharper 将报告为“表达式始终为真”并提示将其删除,即使在这种情况下它绝对不是真的。)

在 C# 的可空性分析中,这似乎是一个足够大的“漏洞”,我不得不怀疑我是否遗漏了一些关于如何让编译器理解这种情况的内容。有没有办法“告诉”编译器 found 结构的字段可能为空,即使它们被声明为不可为空?

编辑:澄清一下,我知道 和this question 的答案,它们解释了为什么会发生这种情况。但我感兴趣的是如何处理它。具体来说,有没有办法告诉编译器某个实例字段可能为空,即使它被标记为不可为空,而无需将该字段的实际声明更改为可空。类似于您如何使用! 后缀表达式来告诉编译器,“相信我,即使它被标记为可空,这也不是空的”,我希望做相反的事情并说“相信我,这可能为 null,即使它被标记为不可为空”。 (如果有办法对结构实例的所有字段自动执行此操作,则可以加分,但我怀疑这是否可能。)

© 版权声明
THE END
喜欢就支持一下吧
点赞54 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片