SQL では、2 つのクエリは次のように変換されます (少なくとも、必要なオブジェクトを選択するために結果の IEnumerables で .FirstOrDefault() を実行する場合):
SELECT TOP (1) [t0].[Number]
FROM [Item] AS [t0]
ORDER BY [t0].[Number] DESC
SELECT TOP (1) [t0].[Number]
FROM [Item] AS [t0]
WHERE [t0].[Number] = ((
SELECT MAX([t1].[Number])
FROM [Item] AS [t1]
))
事実に基づいてどちらが速いかはわかりませんが、最初のオーダーバイソリューションを使用します.
-* データベースのクエリに対応するように編集 *-
メモリ内コレクションをクエリしている場合、違いは非常に小さいはずです。
ただし、以下は、100.000 個の半乱数を 2 つの異なるクエリ方法でそれぞれ 10 回クエリすることによる、まったく非科学的なテストの結果です。
By desc (0): 00:00:00.0173879
By .Max (0): 00:00:00.0132833
By desc (1): 00:00:00.0250781
By .Max (1): 00:00:00.0140374
By desc (2): 00:00:00.0073955
By .Max (2): 00:00:00.0111658
By desc (3): 00:00:00.0066200
By .Max (3): 00:00:00.0115127
By desc (4): 00:00:00.0071220
By .Max (4): 00:00:00.0119572
By desc (5): 00:00:00.0070341
By .Max (5): 00:00:00.0114320
By desc (6): 00:00:00.0066670
By .Max (6): 00:00:00.0111127
By desc (7): 00:00:00.0071905
By .Max (7): 00:00:00.0116715
By desc (8): 00:00:00.0065414
By .Max (8): 00:00:00.0118076
By desc (9): 00:00:00.0071662
By .Max (9): 00:00:00.0131962
LINQPad スクリプト全体を次に示します。
void Main()
{
var listOfItems = new List<Item>();
// Make 100000 Items with semirandom numbers
for(int i=0; i<100000; i++)
{
listOfItems.Add(new Item { Number = i * DateTime.Now.Ticks });
}
for(int i=0; i<10; i++)
{
RunTest(i, listOfItems);
}
}
void RunTest(int count, List<Item> listOfItems)
{
var timer = new System.Diagnostics.Stopwatch();
timer.Start();
// Find by descending
for(int i=0; i<100000; i++)
{
var itemWithLargestNumber =
from item in listOfItems
orderby item.Number descending
select item;
}
timer.Stop();
string.Format("By desc ({0}): {1}", count, timer.Elapsed).Dump();
timer = new System.Diagnostics.Stopwatch();
timer.Start();
// Find by .Max
for(int i=0; i<100000; i++)
{
var itemWithLargestNumber =
from item in listOfItems
where item.Number== (from l in listOfItems select item).Max(l => l.Number)
select item;
}
timer.Stop();
string.Format("By .Max ({0}): {1}", count, timer.Elapsed).Dump();
"".Dump();
}
class Item
{
public long Number { get; set; }
}