在LINQ中获得最大价值的最佳方法?

时间:2018-10-17 08:54:50

标签: linq

我是LINQ的新手。我想知道“日期”的最高值是什么,首选哪种方法?

var ma1x= spResult.Where(p =>p.InstrumentId== instrument).OrderByDescending(u => int.Parse(u.Date)).FirstOrDefault();
var max2= spResult.Where(p =>p.InstrumentId== instrument).Max(u => int.Parse(u.Date));

Max或OrderByDescending吗?

4 个答案:

答案 0 :(得分:2)

Max对开发人员和计算机都更好。

Max总是会更好,因为Max具有语义和意义。

  

Enumerable.Max方法

     

以一系列值返回最大值。

msdn

您想要最大值吗?使用Max。您要订购吗?使用OrderBy。下一位开发人员将感谢您。引用马丁·福勒的话:

  

任何傻瓜都可以编写计算机可以理解的代码。优秀的程序员编写人类可以理解的代码。

如果您真的想至少使用OrderBy来扮演Max的角色,则将orderby和第一个包装在一个有意义的名称的方法中。类似于... Max。太好了,现在您有了一个有意义的OrderBy。

让我们看看这个自定义Max的工作方式。

在最坏的情况下,当Enumerable.Max使用O(n ^ 2)的快速排序时,

OrderBy应该为O(n)。因此,自定义最大值比标准最大值差。

享受绩效奖金,并获得Enumerable.Max。对于开发人员和计算机都更好。

编辑:

检查Marco的answer,看看他们在实践中的表现如何。 race of horses总是一个好主意,知道哪个速度更快。

答案 1 :(得分:1)

.Max()应该更快。首先,该方法的语义更加清晰,您的同事将知道您的调用会做什么。

我已经比较了AdventureWorks2014数据库中的两个选项以及LinqPad中的以下调用:

var times = new List<long>();

for(var i = 0; i < 1000; i++) {
    Stopwatch sw = Stopwatch.StartNew();
    var max2= SalesOrderHeaders.Max(u => u.OrderDate);
    long elapsed = sw.ElapsedMilliseconds;
    times.Add(elapsed);
}
var averageElapsed = times.Sum (t => t) / times.Count();
averageElapsed.Dump(" ms");

生成的SQL:

SELECT MAX([t0].[OrderDate]) AS [value]
FROM [Sales].[SalesOrderHeader] AS [t0]
GO

结果:

  

5毫秒

var times = new List<long>();
for(var i = 0; i < 1000; i++) {
    Stopwatch sw = Stopwatch.StartNew();
    var max1 = SalesOrderHeaders.OrderByDescending(u => u.OrderDate).FirstOrDefault();
    long elapsed = sw.ElapsedMilliseconds;
    times.Add(elapsed);
}
var averageElapsed = times.Sum (t => t) / times.Count();
averageElapsed.Dump(" ms");

生成的SQL:

SELECT TOP (1) [t0].[SalesOrderID], [t0].[RevisionNumber], [t0].[OrderDate], [t0].[DueDate], [t0].[ShipDate], [t0].[Status], [t0].[OnlineOrderFlag], [t0].[SalesOrderNumber], [t0].[PurchaseOrderNumber], [t0].[AccountNumber], [t0].[CustomerID], [t0].[SalesPersonID], [t0].[TerritoryID], [t0].[BillToAddressID], [t0].[ShipToAddressID], [t0].[ShipMethodID], [t0].[CreditCardID], [t0].[CreditCardApprovalCode], [t0].[CurrencyRateID], [t0].[SubTotal], [t0].[TaxAmt], [t0].[Freight], [t0].[TotalDue], [t0].[Comment], [t0].[rowguid] AS [Rowguid], [t0].[ModifiedDate]
FROM [Sales].[SalesOrderHeader] AS [t0]
ORDER BY [t0].[OrderDate] DESC
GO

结果:

  

28ms

结论:Max()更简洁,更快捷!

答案 2 :(得分:0)

纯粹是投机性的,但我会想象max2。它只是遍历每个项目,并检查该值是否高于上一个。 而max1正在检查哪个较高并重新排序。即使只是移动指针(而不是移动值),这仍然需要更多工作。

答案 3 :(得分:0)

Max方法优于FirstOrDefault,它们都将结果发送为true,但是Max的性能很好。

此代码:

var ma1x= spResult.Where(p =>p.InstrumentId== instrument).OrderByDescending(u => int.Parse(u.Date)).FirstOrDefault();

首先检查您的状况,然后根据您的状况对它们进行排序,然后将其选择并采取更多措施来找到您的结果。