链式查询的性能(LINQ to XML)

LINQ(及其 LINQ to XML)最重要的好处之一是,链接查询的性能可以与更大、更复杂的单个查询相媲美。

链接查询是使用另一个查询作为其源的查询。 例如,在以下简单代码中, query2 具有 query1 其源:

XElement root = new XElement("Root",
    new XElement("Child", 1),
    new XElement("Child", 2),
    new XElement("Child", 3),
    new XElement("Child", 4)
);

var query1 = from x in root.Elements("Child")
             where (int)x >= 3
             select x;

var query2 = from e in query1
             where (int)e % 2 == 0
             select e;

foreach (var i in query2)
    Console.WriteLine("{0}", (int)i);
Dim root As New XElement("Root", New XElement("Child", 1), New XElement("Child", 2), New XElement("Child", 3), New XElement("Child", 4))

Dim query1 = From x In root.Elements("Child") Where CInt(x) >= 3x

Dim query2 = From e In query1 Where CInt(e) Mod 2 = 0e

For Each i As var In query2
    Console.WriteLine("{0}", CInt(i))
Next

此示例生成以下输出:

4

此链式查询提供与遍历链接列表相同的性能表现。

  • Elements 本质上与循环访问链接列表的性能相同。 Elements 作为延迟执行的迭代器实现。 这意味着,除了循环访问链接列表之外,它还会执行一些工作,例如分配迭代器对象并跟踪执行状态。 此工作可以分为两个类别:在设置迭代器时完成的工作,以及每次迭代期间完成的工作。 设置工作是少量的固定工时,每次迭代期间完成的工作与源集合中的项数成正比。
  • query1 中,where 语句(Where 在 Visual Basic 中)导致查询调用该 Where 方法。 此方法也作为迭代器实现。 设置工作包括实例化将引用 lambda 表达式的委托和对迭代器的常规设置。 每次迭代时,都将调用该委托以执行谓词。 在每次迭代期间进行的设置工作和其他工作,类似于沿轴线迭代时所完成的工作。
  • query1 中,select 子句会导致查询调用 Select 方法。 此方法的性能概要与该 Where 方法相同。
  • query2中,where子句(在 Visual Basic 中为Where)和select子句具有与query1中相同的性能特性。

因此,通过 query2 的迭代与首次查询源中的项数直接成正比,换句话说,所需时间呈线性增长。

有关迭代器的详细信息,请参阅 yield

有关将查询链接在一起的更详细教程,请参阅教程:将查询链接在一起(C#)。