【问题标题】:HasValue() or ?? operand when dealing with nullable types in LINQ-to-Entity,HasValue() 或 ??处理 LINQ-to-Entity 中的可为空类型时的操作数,
【发布时间】:2021-08-06 04:49:45
【问题描述】:

我有以下代码为可为空的 int 变量赋值:

ParentCommentId = lac.ParentCommentId ?? lac.ParentCommentId.Value,

但是,使用此代码时,我收到了 Nullable object must have a value 错误。

然后,我修改代码如下:

ParentCommentId = lac.ParentCommentId.HasValue ? lac.ParentCommentId.Value : null,

而且,现在一切正常。我想知道为什么 ?? 操作数在这种情况下不起作用。我用错了吗?在什么情况下??会更合适?

【问题讨论】:

  • 为什么不简单地ParentCommentId = lac.ParentCommentId

标签: c# entity-framework linq entity-framework-core linq-to-entities


【解决方案1】:

Nullable object must have a value 是一个运行时异常,当您尝试使用 .HasValue false 访问可空值的 .Value 时发生。

您的代码:

ParentCommentId = lac.ParentCommentId ?? lac.ParentCommentId.Value

被翻译成:

if (lac.ParentCommentId.HasValue)
{
    ParentCommentId = lac.ParentCommentId.Value;
}
else
{
    ParentCommentId = lac.ParentCommentId.Value;
}

如您所见,两个分支都在做同样的事情,即使HasValue 为假,您也将访问.Value(并会导致该异常)。

运算符?? 用于取第一个非空值。你可以写

var value = value1 ?? value2 ?? value3;

value1value2value3 中不是null 的第一个将被分配给value,如果都是null,那么value 将被设置为null

【讨论】:

    【解决方案2】:

    ParentCommentId = lac.ParentCommentId ?? lac.ParentCommentId.Value, 我想知道为什么 ??在这种情况下操作数不起作用。

    当您使用 null-coalescing operator ?? 时,它是一组简短步骤的简写,一般意义上的步骤执行以下操作

    1. lac.ParentCommentId 可以是 null 吗?
      是 -> 继续
      否 -> 给出一个编译器错误,说明您不能在不能为空的东西上使用 ?? 运算符,因为它是 null-coalescing operator

    2. lac.ParentCommentIdnull吗?
      是 -> 继续
      否 -> 将ParentCommentId 的值设置为lac.ParentCommentId 的值,如果它们是相同的类型。

    3. ParentCommentId 的值设置为lac.ParentCommentId.Value 的值,如果它们是相同的类型。

    当您分解 ?? 运算符的作用时,您会发现它在第 2 步附近遇到了问题。

    想要是当lac.ParentCommentId 有值时,将ParentCommentId 设置为lac.ParentCommentId.Value

    但是,当您使用 ?? 时,这不是您正在做的事情。相反,您似乎在说“当lac.ParentCommentId 有值时,将ParentCommentId 设置为lac.ParentCommentId”。

    有一种方法可以解决这个问题,实际上非常简单,因为lac.ParentCommentId 已经是一个可以为空的值,我们可以简单地使用

    ParentCommentId = lac.ParentCommentId ?? AlternativeValue
    

    如果我们还认为nullParentCommentId 的可接受值,我们实际上可以进一步简化它以获得更优雅的解决方案和使用:

    ParentCommentId = lac.ParentCommentId
    

    编辑:以下内容仅适用于 LINQ-to-Objects 而实体框架。它仍然作为? null coelescing 运算符的附加信息。感谢Ivan Stoev 指出这一点!

    如果lac.ParentCommentId.Value 是一个可以为空的值,你可以改用这个:

    ParentCommentId = lac?.ParentCommentId.Value ?? AlternativeValue,
    

    它的作用是检查 lac ParentCommentIdValue 中的 ANY 是否为 null,以及其中的 ANY 是否为 null , 使用替代值。

    【讨论】:

    • 第一部分(问题说明)还可以。但两种解决方法都不是。表达式树不支持空合并运算符?.,因此lac?.ParentCommentId.Value 只是编译时错误。正确的选项是lac.ParentCommentId ?? AlternativeValue。第二个“解决方法”表达式lac.ParentCommentId.HasValue ? lac.ParentCommentId.Value : null 没有任何意义,因为它完全等同于lac.ParentCommentId
    • 是的,你完全正确!我编写了示例解决方案,但误解了这不适用于 LINQ-to-Object,尽管 该帖子实际上是用实体框架标记的!谢谢,我会相应地更新答案。
    • 感谢朋友的详细解释,非常感谢!
    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多