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

Tim*_*ter 14 c# linq

Where在LINQ 中连接多个而不是使用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);
Run Code Online (Sandbox Code Playgroud)

这个简洁的代码将处理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);
}
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ell 14

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

对于你正在做的事情,多重Where是理想的.

  • @sloth好,这是一个*位*取决于正在发生的事情; 但是,在*many*(绝不是全部)情况下,`Iterator <T> .Where(...)`方法将用于组合它们,减少循环. (2认同)
  • @sgarg 当然,看看[这里](https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,165)。在 `WhereEnumerableIterator` 上调用 `Where`(例如,通过组合 `Where` 调用)将导致使用单个 `Iterator`,并且所有谓词只是与 `&amp;&amp;`“组合” (2认同)

Der*_*erd 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;
Run Code Online (Sandbox Code Playgroud)

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

我想这是个人偏好,我喜欢多重因素,因为它的可读性