在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提供商是否重要?
答案 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)的经过时间差异很小,我很确定你可以忽略它。
我猜这是个人偏好,因为它的可读性,我喜欢多重的地方