LINQ:单个具有多个条件的区域和具有单个条件的连续Wheres之间的差异

时间:2014-05-15 09:50:43

标签: c# linq

在LINQ中连接多个Where而不是在多个条件下使用单个Where是否有任何不利之处?

我问,因为使用多个Where可以帮助降低复杂性并大大提高代码的可维护性。

考虑以下代码,chargeList是一个List<Charge>,它是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);

这个简洁的代码将处理filter,none,one,two,all的所有组合。

否则,我必须在一个if-else中使用Where和多个条件。

这是我想到的最好的事情:

// 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);
}

那么两者之间的区别是什么,它们可以忽略不计? LINQ提供商是否重要?

2 个答案:

答案 0 :(得分:14)

从语义上讲,Where(对比OrderBy的情况没有区别,需要更多关注)。在实现级别,它只是具有简单表达式树的多个谓词,而不是具有复杂表达式树的单个谓词;但是大多数引擎都可以应对。

对于你正在做的事情,多个Where是理想的。

答案 1 :(得分:8)

我想知道同样的事情。这就是我在自己的应用程序中尝试这个的原因。

我有一个包含大量条目的列表,这就是我尝试过的:

//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;

每个时间跨度(ts1,ts2,ts3)的经过时间差异很小,我很确定你可以忽略它。

我猜这是个人偏好,因为它的可读性,我喜欢多重的地方