LINQ выполняет оценку короткого замыкания в VB.NET? - PullRequest
0 голосов
/ 05 января 2012

У нас сегодня была ошибка Nullable object must have a value в этой строке кода:

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

Забавно то, что я уверен, что раньше это работало нормально (и в базовых данных всегда было небольшое количество нулевых значений). И по логике это выглядит хорошо для меня. Чек на HasValue и AndAlso выглядят как будто они собираются защитить нас от любой нулевой опасности.

Но, кажется, вдруг это не так. Я что-то упустил?

ОК, мы можем исправить это, что устраняет ошибку:

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, и вынудить меня более внимательно изучить исходную проблему.

Ответы [ 2 ]

1 голос
/ 05 января 2012

должно работать.Я написал этот код, и он прекрасно работает, даже если 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
1 голос
/ 05 января 2012

Я уверен, что ваш запрос безопасен, по крайней мере, следующий пример кода:

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, я быисключение.

Так что проблема должна быть где-то еще.Покажите нам больше своего класса, пожалуйста.

...