双人或三人"其中" Linq中的条款

时间:2015-05-25 06:44:26

标签: c# linq

代码:

var list=GetList()
    .where(x=>x.att01=="X")
    .where(x=>x.att02=="Y")
    .where(x=>x.att03=="Z")
    .SingleOrDefault();

这真的等于

var list=GetList()
    .where(x=>x.att01=="X" && x.att02=="Y" && x.att03=="Z")
    .SingleOrDefault();

我用简单的数组测试了它,它显示它们是相同的。后者似乎做得更好。

2 个答案:

答案 0 :(得分:4)

  

我用简单的数组测试了它,它显示它们是相同的。

从语义上讲,他们都是这样做的。 在这种特殊情况下(正在使用当前的重载),在幕后,WhereEnumerableIterator<TSource>将输出带有链式谓词的单个枚举器:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, 
                                                  Func<TSource, bool> predicate) 
{
    // This is the important line
    if (source is Iterator<TSource>) 
        return ((Iterator<TSource>)source).Where(predicate);
    if (source is TSource[]) 
        return new WhereArrayIterator<TSource>((TSource[])source, predicate);
    if (source is List<TSource>) 
        return new WhereListIterator<TSource>((List<TSource>)source, predicate);
    return new WhereEnumerableIterator<TSource>(source, predicate);
}

IEnumerable<TSource>实际上是WhereEnumerableIterator<TSource>来自Where来电的public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) { return new WhereEnumerableIterator<TSource>(source, CombinePredicates(this.predicate, predicate)); } static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2) { return x => predicate1(x) && predicate2(x); } 。最终,它最终会合并谓词:

SingleOrDefault

但是,Func<TSource, bool>本身有一个过载需要Where,这样就不需要调用var list = GetList().SingleOrDefault(x => x.att01 == "X" && x.att02 == "Y" && x.att03 == "z"); 了:

{{1}}

答案 1 :(得分:4)

鉴于&#34;标准&#34; Enumerable.Where它们完全等效(从结果的角度来看)。第一个将由私人类WhereEnumerableIterator<TSource>转换为第二个,确切地说是通过这种方法:

public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
    return new WhereEnumerableIterator<TSource>(source, CombinePredicates(this.predicate, predicate));
}

将以这种方式组合谓词:

static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2) {
    return x => predicate1(x) && predicate2(x);
}

请参阅x => predicate1(x) && predicate2(x)

从技术上讲,第二个会更快一些,因为第一个会有更多的委托调用,但除非你过滤了数百万行,否则时差可以忽略不计。

请注意,虽然Enumerable.Where做了有趣的技巧,但即使是非智能.Where,例如:

public static class SimpleEnumerable
{
    public static IEnumerable<TSource> SimpleWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        foreach (TSource element in source)
        {
            if (predicate(element))
            {
                yield return element;
            }
        }
    }
}

完全相同(但更慢!)。请参阅此处的示例:https://ideone.com/QAQZ65