【问题标题】:NullReferenceException when using Group.FirstOrDefault with Value Type将 Group.FirstOrDefault 与值类型一起使用时出现 NullReferenceException
【发布时间】:2013-07-26 14:22:15
【问题描述】:

这是一个 linq 表达式的摘录:

Dim charges As List(Of IndividualCharge) = (From t In totals
                    Group t By t.InvId
                    Into Group
                    Select New IndividualCharge With {
                    .VatRate = Group.FirstOrDefault(Function(x) x.VatRate).VatRate
                    }).ToList()

看来x.VatRate0时,FirstOrDefault抛出异常:

我可以通过换掉它来确认这一点:

.VatRate = Group.FirstOrDefault(Function(x) 0).VatRate

确保每次都出现异常。

  • 为什么会抛出空引用异常(这是一个值类型,因此没有引用)?
  • x.VatRate 实际上是0 的情况如何处理?

【问题讨论】:

  • @Skippy - 意义不相关
  • 我没有像你想的那样做任何除法
  • 在这种情况下它只是一个数字

标签: .net vb.net linq linq-expressions


【解决方案1】:

您误读了错误,加上 VB.NET 的类型强制。

Group.FirstOrDefault(Function(x) x.VatRate).VatRate

FirstOrDefault 返回与谓词函数匹配的第一个值,如果没有匹配项,则返回默认值 T。由于您的函数不会评估为truefalse,VB.NET 将int 强制为bool。在那种情况下,0 is converted to false and any other value is converted to true

所以,当x.VatRate 不是0 时,那么第一个IndividualCharge 通过谓词过滤器。当VatRate0 时,则没有IndividualCharge 通过谓词过滤器并返回null(默认值IndividualCharge)。尝试获取VatRate 然后会导致您的NullReferenceException

大概你真的想要第一个VatRate,不管它是否为0。将您的代码更改为:

Group.Select(Function(x) x.VatRate).First()

应该做到这一点。

【讨论】:

    【解决方案2】:

    当您将表达式传递给 FirstOrDefault 时,您会告诉它选择与表达式匹配的第一个项目(很像 Where 子句,但要匹配该子句的第一个对象)。如果您将您的陈述更改为以下内容可以吗?

    Dim charges As List(Of IndividualCharge) = (From t In totals
                        Group t By t.InvId
                        Into Group
                        Select New IndividualCharge With {
                        .VatRate = Group.FirstOrDefault().VatRate
                        }).ToList()
    

    如果您想获得第一个不为零的值,那么应该按照这些方式进行操作?

    Dim charges As List(Of IndividualCharge) = (From t In totals
                        Group t By t.InvId
                        Into Group
                        Select New IndividualCharge With {
                        .VatRate = if(Group.Any(function(o) o.VatRate > 0),  Group.FirstOrDefault(function(o) o.VatRate > 0).VatRate, -1)
                        }).ToList()
    

    【讨论】:

      【解决方案3】:

      这是由 VB 的隐式类型强制导致的。 FirstOrDefault 方法需要一个返回 Boolean 的函数。您正在传递一个返回 Decimal 的函数,因此 VB 将其转换为:

      Group.FirstOrDefault(Function(x) x.VatRate <> 0)
      

      如果组中的所有项目都没有非零的VatRate,这将返回Nothing。然后,您尝试访问返回对象的 VatRate 属性,这会导致 NullReferenceException

      尝试使用:

      Group.Where(Function(x) x.VatRate <> 0)
         .Select(Function(x) x.VatRate)
         .FirstOrDefault()
      

      如果有一个,则应该返回第一个非零VatRate,否则返回零。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-28
        • 1970-01-01
        • 2019-03-20
        • 2021-11-21
        • 2021-05-12
        • 1970-01-01
        • 2013-12-31
        • 2020-06-27
        相关资源
        最近更新 更多