LINQ 在 VB.NET 中进行短路评估吗?

发布于 2024-12-25 11:57:43 字数 1148 浏览 0 评论 0原文

今天,我们在这行代码上遇到了 Nullable object must have a value 错误:

list = From x In Me Where x.FooDate.HasValue AndAlso x.FooDate.Value.Date >= barDate

有趣的是,我确信这曾经工作得很好(并且底层中总是有一些空值)数据)。从逻辑上讲,它对我来说看起来不错。对 HasValueAndAlso 的检查看起来好像它们会保护我们免受任何 Null 危险。

但突然间他们似乎就不是了。我错过了什么吗?

好的,我们可以更正它,从而消除错误:

list = From x In Me Where If(x.FooDate.HasValue, x.FooDate.Value.Date >= barDate,False)

但这在我看来不太可读。有什么想法吗?

更新...和忏悔
在简化上面的代码以缩短代码行时,我遗漏了代码的关键部分。最初的问题应该是这样的:

list = From x In Me Where x.FooDate.HasValue AndAlso x.FooDate.Value.Date >= fromDate And x.FooDate.Value.Date <= toDate

因为短路和运算符优先级的规则(如在答案中概述很久以前我自己的问题)我需要在指令的第二部分周围添加括号,以便停止 LINQ 评估第二个 x.FooDate.Value.Date

list = From x In Me Where x.FooDate.HasValue AndAlso (x.FooDate.Value.Date >= fromDate and x.FooDate.Value.Date <= toDate)

感谢两个答案的抛出快速测试代码来验证 LINQ 确实遵守 AndAlso 并迫使我更仔细地查看原始问题。

We had a Nullable object must have a value error today on this line of code:

list = From x In Me Where x.FooDate.HasValue AndAlso x.FooDate.Value.Date >= barDate

Funny thing is that I feel sure this used to work fine (and there has always been a sprinkling of null values in the underlying data). And logically it looks fine to me. The check for HasValue and the AndAlso look as if they're going to shield us from any Null danger.

But it seems suddenly they're not. Am I missing something?

OK, we can correct it to this, which eliminates the error:

list = From x In Me Where If(x.FooDate.HasValue, x.FooDate.Value.Date >= barDate,False)

But this looks to me less readable. Any thoughts?

Update ... and Confession:
In simplifying the above code to shorten the line I left out a crucial chunk of the code. The original problem should have read something like:

list = From x In Me Where x.FooDate.HasValue AndAlso x.FooDate.Value.Date >= fromDate And x.FooDate.Value.Date <= toDate

Because of the rules of shortcircuiting and operator precedence (as outlined in an answer to a long ago question of my own) I needed to add brackets round the second part of the instruction in order to stop LINQ evaluating the second x.FooDate.Value.Date:

list = From x In Me Where x.FooDate.HasValue AndAlso (x.FooDate.Value.Date >= fromDate and x.FooDate.Value.Date <= toDate)

Thanks to both answers for throwing up quick test code to verify that LINQ really does obey AndAlso and force me to look more closely at the original problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

随波逐流 2025-01-01 11:57:43

我很确定您的查询是安全的,至少以下示例代码是:

Dim dateList As New List(Of Nullable(Of Date))
For i As Int32 = 0 To 12
    If (i Mod 3 = 0) Then
        dateList.Add(Nothing)
    Else
        dateList.Add(New Date(2012, i, 1))
    End If
Next
Dim july = New Date(2012, 7, 1)
Dim fromJuly = (From m In dateList
      Where m.HasValue AndAlso m.Value.Date >= july).ToList

注意:如果我将 AndAlso 替换为 And 我会得到您的异常。

所以问题一定出在其他地方。请向我们展示更多您的课程。

I'm pretty sure that your query is safe, at least following sample code is:

Dim dateList As New List(Of Nullable(Of Date))
For i As Int32 = 0 To 12
    If (i Mod 3 = 0) Then
        dateList.Add(Nothing)
    Else
        dateList.Add(New Date(2012, i, 1))
    End If
Next
Dim july = New Date(2012, 7, 1)
Dim fromJuly = (From m In dateList
      Where m.HasValue AndAlso m.Value.Date >= july).ToList

Note: If i would replace AndAlso with And i would get your exception.

So the problem must be somewhere else. Show us more of your class please.

天涯沦落人 2025-01-01 11:57:43

它应该有效。我编写了这段代码,即使将 barDate 设置为 Nothing,它对我来说也很好用。

Sub Main()

    Dim barDate As Nullable(Of DateTime) = Nothing

    Dim List = From x In GetDates() Where x.FooDate.HasValue AndAlso x.FooDate.Value.Date > barDate

    Console.WriteLine(List.Count())

End Sub

Function GetDates() As List(Of Foo)
    Dim l = New List(Of Foo)
    l.Add(New Foo With {.FooDate = DateTime.Now})
    l.Add(New Foo)
    Return l
End Function

Class Foo
    Private m_fooDate As DateTime?
    Public Property FooDate() As DateTime?
        Get
            Return m_fooDate
        End Get
        Set(ByVal value As DateTime?)
            m_fooDate = value
        End Set
    End Property

End Class

It should work. I wrote this code, and it works for me fine, even with barDate set to Nothing.

Sub Main()

    Dim barDate As Nullable(Of DateTime) = Nothing

    Dim List = From x In GetDates() Where x.FooDate.HasValue AndAlso x.FooDate.Value.Date > barDate

    Console.WriteLine(List.Count())

End Sub

Function GetDates() As List(Of Foo)
    Dim l = New List(Of Foo)
    l.Add(New Foo With {.FooDate = DateTime.Now})
    l.Add(New Foo)
    Return l
End Function

Class Foo
    Private m_fooDate As DateTime?
    Public Property FooDate() As DateTime?
        Get
            Return m_fooDate
        End Get
        Set(ByVal value As DateTime?)
            m_fooDate = value
        End Set
    End Property

End Class
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文