LINQ: differences between single Where with multiple conditions and consecutive Wheres with single condition [duplicate]

StackOverflow https://stackoverflow.com/questions/23674778

  •  23-07-2023
  •  | 
  •  

Is there any disadvantage in concatenating multiple Where in LINQ instead of using a single Where with multiple conditions?

I'm asking because using multiple Where can help to reduce complexity and improve maintainability of my code considerably.

Consider following code, chargeList is a List<Charge> which is the source of a BindingSource:

IEnumerable<Charge> matchingCharges = chargeList;
if(!string.IsNullOrWhiteSpace(channelAbbr))
    matchingCharges = matchingCharges
        .Where(c => c.ChannelAbbreviation == channelAbbr);
if(deliveryNoteDate.HasValue)
    matchingCharges = matchingCharges
        .Where(c => c.ArrivalAt == deliveryNoteDate.Value);
if(chargeID.HasValue)
    matchingCharges = matchingCharges
        .Where(c => c.ChargeID == chargeID.Value);

This concise code will handle all combinations of filter, none,one,two,all.

Otherwise i'd have to use if-else and multiple conditions in a single Where.

This is the best that comes to my mind:

// important to keep code readable:
bool filterChannel = !string.IsNullOrWhiteSpace(channelAbbr);
bool filterDate = deliveryNoteDate.HasValue;
bool filterID = chargeID.HasValue;

if(!filterChannel && !filterDate && !filterID)
{
    // take all 
    matchingCharges = chargeList;
}
else
{
    matchingCharges = chargeList
        .Where(c => 
            filterChannel ? c.ChannelAbbreviation == channelAbbr : true
            && filterDate ? c.ArrivalAt == deliveryNoteDate.Value : true
            && filterID   ? c.ChargeID ==  chargeID.Value : true);
}

So what are the differences between both, are they negligible? Does the LINQ provider matter?

有帮助吗?

解决方案

Semantically, there is no difference in the case of Where (contrast OrderBy, which needs more care). At the implementation level, it is simply multiple predicates with simple expression trees instead of a single predicate with a complex expression tree; but most engines will cope fine with either.

For what you are doing, multiple Where is ideal.

其他提示

I was wondering the same thing. That's why I tried this in my own application.

I have a list with a lot of entries and this is what I tried:

//TEST 1
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var hoursLinq = _hourDataSource.Hours
            .Where(hour => hour.Id == profile.Id)
            .Where(hour => hour.DayName.Equals("Maandag"))
            .Where(hour => hour.Day == 1)
            .Select(hour => hour);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts1 = stopWatch.Elapsed;

//TEST 2
stopWatch = new Stopwatch();
stopWatch.Start();
var hoursLinq2 = _hourDataSource.Hours
            .Where(hour => hour.Id == profile.Id)
            .Select(hour => hour);

if (hoursLinq2.Count() != 0)
{
    var hoursLinq3 = _hourDataSource.Hours
            .Where(hour => hour.DayName.Equals("Maandag"))
            .Select(hour => hour);

    if (hoursLinq3.Count() != 0)
    {
        var hoursLinq4 = _hourDataSource.Hours
            .Where(hour => hour.Day == 1)
            .Select(hour => hour);
    }
}

stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts2 = stopWatch.Elapsed;

//TEST 3
stopWatch = new Stopwatch();
stopWatch.Start();
var hoursLinq5 = _hourDataSource.Hours
            .Where(hour => hour.Id == profile.Id &&
                            hour.DayName.Equals("Maandag") &&
                            hour.Day == 1)
            .Select(hour => hour);

stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts3 = stopWatch.Elapsed;

Each timespan (ts1, ts2, ts3) had such a small difference in elapsed time that I'm pretty sure you can ignore it.

I guess it's personal preference, I like the multiple where's because of it's readability

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top