CodingBarfield
CodingBarfield

Reputation: 3398

Vb.net conditional linq query

In this query against a datatable i'm trying to do some conditional filtering. The check against Timeband(index N) should only be done when the Index exists. (the base code only had three item fields, i've converted them to a simple list)

Dim res As DataTable =
    (
        From dr As DataRow In dtTimedRow.AsEnumerable()
        Select dr
        Where
        (TimeBands.Count > 0 AndAlso
         dr.Field(Of Short)(fldStarttime) >= TimeBands(0).StartTime
         And dr.Field(Of Short)(fldStarttime) <= TimeBands(0).EndTime
        ) Or
        (TimeBands.Count > 1 AndAlso
         dr.Field(Of Short)(fldStarttime) >= TimeBands(1).StartTime
         And dr.Field(Of Short)(fldStarttime) <= TimeBands(1).EndTime
        ) Or
        (TimeBands.Count > 2 AndAlso
         dr.Field(Of Short)(fldStarttime) >= TimeBands(2).StartTime
         And dr.Field(Of Short)(fldStarttime) <= TimeBands(2).EndTime)
    ).CopyToDataTable()

The above code triggers an Exception if the count = 1. It executes the code next to imeBands.Count > 1 which it should not. What would be the correct solution for this code.

In the mean time i've added a simple filter function.

Upvotes: 1

Views: 1159

Answers (1)

Heinzi
Heinzi

Reputation: 172280

The problem is that you use And when you should be using AndAlso:

TimeBands.Count > 2
AndAlso dr.Field(Of Short)(fldStarttime) >= TimeBands(2).StartTime (= cond1)
And dr.Field(Of Short)(fldStarttime) <= TimeBands(2).EndTime (= cond2)

Since And and AndAlso have the same operator precedence, this is evaluated left-to-right as follows:

(TimeBands.Count > 2 AndAlso cond1) And cond2

And does not short-circuit, i.e., the right-hand side of the expression (cond2) is always evaulated, yielding an exception when TimeBands.Count <= 2. Change all your Ands to AndAlsos, and you should be fine:

TimeBands.Count > 2 AndAlso cond1 AndAlso cond2

An alternative would be to put parenthesis like this:

TimeBands.Count > 2 AndAlso (cond1 And cond2)

but that's just wasting performance. Since cond1 and cond2 don't have side effects, there's no reason to avoid short-circuiting. For the same reasons, I recommend to also change your Ors to the short-circuiting variant OrElse.

Upvotes: 3

Related Questions