System.NullReferenceException 使用 null 合并运算符时出现异常

System.NullReferenceException when using null coalescing operator

提问人:PhillyD 提问时间:1/29/2020 最后编辑:PhillyD 更新时间:1/30/2020 访问量:1200

问:

我遇到了一个似乎无法修复的错误。在对 Stack Overflow 进行了一些研究后,似乎 null 合并运算符是解决我问题的方法,但它没有帮助。下面是给出错误的代码:

List<OperationsReviewLevelResult> results = new List<OperationsReviewLevelResult>();
foreach (var approval in OperationsReviewers.ApprovalItems)
{
     var result = new OperationsReviewLevelResult();
     result.ApproverName = approval.Results.FirstOrDefault().Name ?? "";
     result.ReviewLevel = approval.Name;
     result.Comment = approval.Results.FirstOrDefault().Comments ?? "";
     results.Add(result);
}

当我运行这段代码时,我得到:

异常详细信息:System.NullReferenceException:对象引用未设置为对象的实例。

来自线.我添加了 null 合并运算符来检查 null 值,但这并不能解决我的问题。错误是因为没有批准,所以我假设 linq 方法将返回默认值,当它意识到默认值为 时,它将使用 null 合并运算符返回运算符右侧的空字符串。result.ApproverName = approval.Results.FirstOrDefault().Name ?? "";ResultsFirstOrDefaultName""

如果我遗漏了什么,请告诉我,因为我似乎不明白为什么即使在添加 null 合并运算符时也会出现此错误。

编辑:正如评论中所建议的那样,查看这篇文章帮助我更多地了解了为什么我收到此错误。虽然问题有点不同,但我强烈建议您阅读答案以全面了解我的问题。

C# .NET LINQ NullReferenceException

评论

2赞 Nekeniehl 1/29/2020
因为你正在访问 null。名称,请尝试使用批准。Results.FirstOrDefault()?。名字
3赞 Dmitry Bychenko 1/29/2020
大概因为可以好好回来.FirstOrDefault()?.FirstOrDefault()null
1赞 Lasse V. Karlsen 1/29/2020
你只检查 is 、if is null、is null 或返回 null,你仍然会得到该异常。您需要在任何可能为空的序列点的点之前添加一个问号。假设你有 ,并且只想处理 if returns ,你可以有Namenullapprovalapproval.Resultsapproval.Results.FirstOrDefault()approval.ResultsFirstOrDefault()null= approval.Results.FirstOrDefault()?.Name ?? "";
1赞 Lasse V. Karlsen 1/29/2020
如果所有涉及的标识符都可以为 null,则需要完整的= approval?.Results?.FirstOrDefault()?.Name ?? "";
0赞 Lasse V. Karlsen 1/29/2020
如果你有一个表达式,它不会神奇地将里面所有可能的空引用变成计算,它只检查计算的最终结果是否最终是 ,那么你会得到 。在你的例子中,你有几个地方仍然取消引用某些东西,它们都可能抛出这个异常。a ?? banullanullb

答:

7赞 Kit 1/29/2020 #1

每次通话后,您都需要添加接线员。这是一个完整的解决方案:.FirstOrDefault()?.

List<OperationsReviewLevelResult> results = new List<OperationsReviewLevelResult>();
foreach (var approval in OperationsReviewers.ApprovalItems)
{
     var result = new OperationsReviewLevelResult();
     result.ApproverName = approval.Results.FirstOrDefault()?.Name ?? "";
     result.ReviewLevel = approval.Name;
     result.Comment = approval.Results.FirstOrDefault()?.Comments ?? "";
     results.Add(result);
}

如果结果的其他部分可能为空,您可以走完全偏执的路线

List<OperationsReviewLevelResult> results = new List<OperationsReviewLevelResult>();
foreach (var approval in OperationsReviewers.ApprovalItems)
{
     var result = new OperationsReviewLevelResult();
     result.ApproverName = approval?.Results?.FirstOrDefault()?.Name ?? "";
     result.ReviewLevel = approval?.Name;
     result.Comment = approval?.Results?.FirstOrDefault()?.Comments ?? "";
     results.Add(result);
}

偏执狂和 LINQ 化:

var results = OperationsReviewers.ApprovalItems
    .Select(approval => new OperationsReviewLevelResult
    {
        ApproverName = approval?.Results?.FirstOrDefault()?.Name ?? "",
        ReviewLevel = approval?.Name,
        Comment = approval?.Results?.FirstOrDefault()?.Comments ?? ""
    }
    .ToList();
7赞 Dmitry Bychenko 1/29/2020 #2

最可能的原因是返回(作为默认值),从而引发异常。 您可以借助以下方法尝试 null 传播FirstOrDefault()nullFirstOrDefault().Name?.

   foreach (var approval in OperationsReviewers.ApprovalItems)
     results.Add(new OperationsReviewLevelResult() {
       ApproverName = approval.Results.FirstOrDefault()?.Name ?? "",
       ReviewLevel  = approval.Name,
       Comment      = approval.Results.FirstOrDefault()?.Comments ?? "",
     });

所以如果是的,因此返回,然后返回,最终变成approval.ResultsFirstOrDefault()nullFirstOrDefault()?.Namenull""

评论

0赞 PhillyD 1/29/2020
谢谢!我更多地研究了零传播,并能够用你的答案解决我的问题:)