趁著最近空閒,來整理一下從 .NET 6 之後 Linq 上的新功能。
本集提要
- 框架 : .NET 6
- 功能 : MaxBy, MinBy
說明
Linq 的 Max與Min 方法可以協助我們取得一串執行個體中某個屬性的最大值或最小值,當我們想要取得的是具有最大值或最小值的執行個體就得要拐彎。
例如有以下序列:
var people = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 },
new Person { Name = "Charlie", Age = 35 }
};
如果要取得最大的年齡,通常我們會這麼寫:
int maxAge = people.Max(p => p.Age);
但需求如果是要取得具有最大年齡的那個執行個體,可能會有一些其他做法,例如 (先不考慮強固性的問題):
(1) 先 OrderByDescending 再 First
Person oldestPerson1 = people.OrderByDescending(p => p.Age).First();
(2) 先取 Max 再 First
int maxAge = people.Max(p => p.Age);
Person oldestPerson2 = people.First(p => p.Age == maxAge);
老實說也沒真的很難啦。不過微軟在 .NET 6 提供了更方便的方法,MaxBy 與 MinBy:
Person oldestPerson3 = people.MaxBy(p => p.Age);
Person youngestPerson3 = people.MinBy(p => p.Age);
上述的範例在此。
Benchmark
我也好奇測試了一下效能,MaxBy 和 MinBy 似乎比舊式的方式要快一些,而且使用更少的記憶體,可以在這邊看到 Benchmark 測試的程式碼。
兩次記錄的結果如下:
// * Summary *
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4751/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1265U, 1 CPU, 12 logical and 10 physical cores
.NET SDK 9.0.200-preview.0.24575.35
[Host] : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
DefaultJob : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|------------------------- |---------:|----------:|----------:|-------:|----------:|
| CallOrderByDescThenFirst | 4.348 us | 0.0579 us | 0.0542 us | 0.0153 | 128 B |
| CallMaxThenFirst | 4.446 us | 0.0699 us | 0.0653 us | 0.1144 | 760 B |
| CallMaxBy | 3.727 us | 0.0327 us | 0.0306 us | 0.0038 | 40 B |
| CallOrderByThenFirst | 4.913 us | 0.0583 us | 0.0545 us | 0.0153 | 128 B |
| CallMinThenFirst | 3.870 us | 0.0435 us | 0.0407 us | 0.0381 | 280 B |
| CallMinBy | 3.654 us | 0.0565 us | 0.0501 us | 0.0038 | 40 B |
// * Summary *
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4751/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1265U, 1 CPU, 12 logical and 10 physical cores
.NET SDK 9.0.200-preview.0.24575.35
[Host] : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
DefaultJob : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|------------------------- |---------:|----------:|----------:|-------:|----------:|
| CallOrderByDescThenFirst | 4.406 us | 0.0863 us | 0.0848 us | 0.0153 | 128 B |
| CallMaxThenFirst | 4.511 us | 0.0591 us | 0.0553 us | 0.1068 | 712 B |
| CallMaxBy | 3.659 us | 0.0350 us | 0.0292 us | 0.0038 | 40 B |
| CallOrderByThenFirst | 4.730 us | 0.0684 us | 0.0640 us | 0.0153 | 128 B |
| CallMinThenFirst | 3.944 us | 0.0670 us | 0.0627 us | 0.0763 | 520 B |
| CallMinBy | 3.633 us | 0.0588 us | 0.0550 us | 0.0038 | 40 B |