.NET 6 中的 LINQ 更新
.NET 6 中的 LINQ 更新
Intro
在 .NET 6 中會針對 Linq 提供更好的支持,之前可能我們通過自定義擴展方法來實現(xiàn)的功能,現(xiàn)在官方直接支持了。Linq 將更加強大,更好地幫助我們簡化應(yīng)用程序代碼。
Better Index & Range support
Index 和 Range 是在 C# 8.0 開始引入的一個特性,可以幫助我們更好地定位元素的位置或者在原有集合的基礎(chǔ)上進行切片操作,.NET 6 會更好地支持 Index 和 Range 特性以及對 Linq 更好的支持,來看下面的示例:
Enumerable.Range(1, 10).ElementAt(^2).Dump(); // returns 9
Enumerable.Range(1, 10).Take(^2..).Dump(); // returns [9,10]
Enumerable.Range(1, 10).Take(..2).Dump(); // returns [1,2]
Enumerable.Range(1, 10).Take(2..4).Dump(); // returns [3,4]
XxxBy Clause
.NET 6 將引入 XxxBy 來支持按照集合內(nèi)的元素來進行 Max/Min/Union/Distinct/Intersect/Except 等操作。
// DistinctBy/UnionBy/IntersectBy/ExceptBy
Enumerable.Range(1, 20).DistinctBy(x => x % 3).Dump();// [1, 2, 3]
var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) };
first.UnionBy(second, person => person.Age).Select(x=>$"{x.Name}, {x.Age}").Dump(); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }
// MaxBy/MinBy
var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
people.MaxBy(person => person.Age).Dump(); // ("Ashley", 40)
people.MinBy(x => x.Name).Dump(); // ("Ashley", 40)
Chuck
這個功能期待已久了,簡單來說就是按 BatchSize 對一個集合進行分組,分組后每個小集合的元素數(shù)量最多是 BatchSize,之前我們自己寫了一個擴展方法來實現(xiàn),現(xiàn)在可以直接使用這個擴展方法了,來看下面的示例就能夠明白了:
var list = Enumerable.Range(1, 10).ToList();
var chucks = list.Chunk(3);
chucks.Dump();
// [[1,2,3],[4,5,6],[7,8,9],[10]]
Default enhancement
針對于 FirstOrDefault/LastOrDefault/SingleOrDefault 這幾個擴展方法,之前的版本中我們是不能夠指定默認值的,如果遇到 Default 的情況,會使用泛型類型的默認值,在 .NET 6 之后我們就可以指定一個默認值了,示例如下:
Enumerable.Empty<int>().FirstOrDefault(-1).Dump();
Enumerable.Empty<int>().SingleOrDefault(-1).Dump();
Enumerable.Empty<int>().LastOrDefault(-1).Dump();
Zip enhancement
var xs = Enumerable.Range(1, 5).ToArray();
var ys = xs.Select(x => x.ToString());
var zs = xs.Select(x => x % 2 == 0);
foreach (var (x,y,z) in xs.Zip(ys, zs))
{
$"{x},{y},{z}".Dump();
}
輸出結(jié)果如下:
1,1,False
2,2,True
3,3,False
4,4,True
5,5,False
More
除了上面的更新之外,微軟還提供了一個 TryGetNonEnumeratedCount(out int count) 方法來嘗試獲取 Count ,這樣如果 IEnumerable<T> 是一個 ICollection 對象就能比較高效地獲取 Count,而不用調(diào)用 Count() 擴展方法,不需要遍歷 IEnumerable 對象
另外針對原來的 Min/Max 擴展方法,.NET 6 會增加一個重載,可以比較方便地指定一個比較器
public static TSource Min<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer);
public static TSource Max<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer);
public static TSource Min<TSource>(this IQueryable<TSource> source, IComparer<TSource> comparer);
public static TSource Max<TSource>(this IQueryable<TSource> source, IComparer<TSource> comparer);
References
https://github.com/WeihanLi/SamplesInPractice/blob/master/net6sample/LinqSample/Program.cs https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/#system-linq-enhancements .NET 6 Preview 4 Released

