我今天看到了我的项目中的linq查询语法 List
特定条件的项目:
int temp = (from A in pTasks
where A.StatusID == (int)BusinessRule.TaskStatus.Pending
select A).ToList().Count();
我想通过写它就像使用它来重构它 Count()
为了使更多的可读性和我认为它将是性能明智也好,所以我写道:
int UnassignedCount = pTasks.Count(x => x.StatusID == (int)BusinessRule.TaskStatus.Pending);
但是当我通过推杆检查 StopWatch
lambda表达式所经历的时间总是超过查询synax:
Stopwatch s = new Stopwatch();
s.Start();
int UnassignedCount = pTasks.Count(x => x.StatusID == (int)BusinessRule.TaskStatus.Pending);
s.Stop();
Stopwatch s2 = new Stopwatch();
s2.Start();
int temp = (from A in pTasks
where A.StatusID == (int)BusinessRule.TaskStatus.Pending
select A).ToList().Count();
s2.Stop();
有人可以解释为什么会这样吗?
我模拟了你的情况。是的,这些查询的执行时间之间存在差异。但是,这种差异的原因不是查询的语法。如果您使用了方法或查询语法,则无关紧要。两者都产生相同的结果,因为 查询表达式被翻译成他们的lambda表达式 在他们编译之前。
但是,如果您已经注意到两个查询完全不相同。您的第二个查询将在编译之前被转换为它的lambda语法(你可以删除 ToList()
就像Farhad所说,Where(x).Count()和Count(x)的实现各不相同。第一个实例化一个额外的迭代器,在我的电脑上花费大约30.000个刻度(无论集合大小)
此外,ToList不是免费的。它分配内存。这需要时间。在我的电脑上,它大约是执行时间的两倍。 (所以线性相关op集合大小)
此外,调试需要启动时间。因此,一次性精确测量性能很困难。我推荐一个像这个例子的循环。然后,忽略第一组结果。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var pTasks = Task.GetTasks();
for (int i = 0; i < 5; i++)
{
var s1 = Stopwatch.StartNew();
var count1 = pTasks.Count(x => x.StatusID == (int) BusinessRule.TaskStatus.Pending);
s1.Stop();
Console.WriteLine(s1.ElapsedTicks);
var s2 = Stopwatch.StartNew();
var count2 =
(
from A in pTasks
where A.StatusID == (int) BusinessRule.TaskStatus.Pending
select A
).ToList().Count();
s2.Stop();
Console.WriteLine(s2.ElapsedTicks);
var s3 = Stopwatch.StartNew();
var count3 = pTasks.Where(x => x.StatusID == (int) BusinessRule.TaskStatus.Pending).Count();
s3.Stop();
Console.WriteLine(s3.ElapsedTicks);
var s4 = Stopwatch.StartNew();
var count4 =
(
from A in pTasks
where A.StatusID == (int) BusinessRule.TaskStatus.Pending
select A
).Count();
s4.Stop();
Console.WriteLine(s4.ElapsedTicks);
var s5 = Stopwatch.StartNew();
var count5 = pTasks.Count(x => x.StatusID == (int) BusinessRule.TaskStatus.Pending);
s5.Stop();
Console.WriteLine(s5.ElapsedTicks);
Console.WriteLine();
}
Console.ReadLine();
}
}
public class Task
{
public static IEnumerable<Task> GetTasks()
{
for (int i = 0; i < 10000000; i++)
{
yield return new Task { StatusID = i % 3 };
}
}
public int StatusID { get; set; }
}
public class BusinessRule
{
public enum TaskStatus
{
Pending,
Other
}
}
}