Linq查询性能,比较编译查询与非编译查询

net*_*x01 1 c# linq functional-programming

我想知道如果我将常见的where子句查询提取到一个公共表达式中它会使我的查询更快,如果我在一个集合上说10个linq查询的东西与where子句的完全相同的第一部分.

我做了一个小例子来解释一下.

public class  Person
{
    public string First { get; set; }
    public string Last { get; set; }
    public int Age { get; set; }
    public String Born { get; set; }
    public string Living { get; set; }
}

public sealed class PersonDetails : List<Person>
{
}



PersonDetails d = new PersonDetails();
        d.Add(new Person() {Age = 29, Born = "Timbuk Tu", First = "Joe", Last = "Bloggs", Living = "London"});
        d.Add(new Person() { Age = 29, Born = "Timbuk Tu", First = "Foo", Last = "Bar", Living = "NewYork" });

        Expression<Func<Person, bool>> exp = (a) => a.Age == 29;
        Func<Person, bool> commonQuery = exp.Compile();

        var lx = from y in d where commonQuery.Invoke(y) && y.Living == "London" select y;

        var bx = from y in d where y.Age == 29 && y.Living == "NewYork" select y;

        Console.WriteLine("All Details {0}, {1}, {2}, {3}, {4}", lx.Single().Age, lx.Single().First , lx.Single().Last, lx.Single().Living, lx.Single().Born );
        Console.WriteLine("All Details {0}, {1}, {2}, {3}, {4}", bx.Single().Age, bx.Single().First, bx.Single().Last, bx.Single().Living, bx.Single().Born);
Run Code Online (Sandbox Code Playgroud)

如果像编写查询一样好的做法,那么这里的一些大师可以给我一些建议

 var lx = "Linq Expression "
Run Code Online (Sandbox Code Playgroud)

要么

 var bx = "Linq Expression" ?
Run Code Online (Sandbox Code Playgroud)

任何投入都将受到高度赞赏.

谢谢,AG

Jon*_*eet 6

首先,Eric绝对正确:如果你关注性能,你需要测量它.准确计算出您想要衡量的内容,并记录您在代码中所做的每项更改会发生什么.基准测试的各个方面我现在没有时间进行,但关键的一个方面可能是确保你运行测试足够长的时间让它们变得有意义 - 如果你的测试只需要50ms,你就是不太可能从噪音中分辨出代码的改进.

现在,如果您正在使用LINQ to Objects,那么您几乎肯定不想使用表达式树.坚持代表 - 这就是LINQ to Objects所使用的.

现在,至于重组......如果你有一个共同的谓词,那么你可以按照那个过滤你的列表,想出一个新的IEnumerable<T>.谓词将被懒惰地应用,因此它不会对执行速度产生任何影响,但它可能会使您的代码更具可读性.当你有效地获得两个不同的子句时,它可能会使事情变得非常缓慢,因为它会引入额外的间接性where.

如果应用过滤器的结果只有非常少的结果,您可能希望实现它(例如通过调用ToList)并记住结果 - 这样您就不需要再次查询第二个查询的全部内容.

但是,我能看到的最大好处是只Single为每个查询调用一次.目前,您正在为每个属性执行整个查询 - 这显然效率低下.

这是您的代码,相应地重写 - 并使用集合初始化程序:

PersonDetails d = new PersonDetails
{
    new Person {Age = 29, Born = "Timbuk Tu", First = "Joe", 
               Last = "Bloggs", Living = "London"},
    new Person { Age = 29, Born = "Timbuk Tu", First = "Foo", 
                Last = "Bar", Living = "NewYork" }
};

var peopleOfCorrectAge = d.Where(a => a.Age == 29);

var londoners = peopleOfCorrectAge.Where(p => p.Living == "London");
var newYorkers = peopleOfCorrectAge.Where(p => p.Living == "New York");

var londoner = londoners.Single();
var newYorker = newYorker.Single();

Console.WriteLine("All Details {0}, {1}, {2}, {3}, {4}",
                  londoner.Age, londoner.First, 
                  londoner.Last, londoner.Living, londoner.Born);

Console.WriteLine("All Details {0}, {1}, {2}, {3}, {4}",
                  newYorker.Age, newYorker.First, 
                  newYorker.Last, newYorker.Living, newYorker.Born);
Run Code Online (Sandbox Code Playgroud)

或者,对于最后一部分,封装"写出一个人":

DisplayPerson(londoners.Single());
DisplayPerson(newYorkers.Single());

...

private static void DisplayPerson(Person person)
{
    Console.WriteLine("All Details {0}, {1}, {2}, {3}, {4}",
                      person.Age, person.First, 
                      person.Last, person.Living, person.Born);
}
Run Code Online (Sandbox Code Playgroud)