.NET 6 中的 LINQ 改进
*或缺省方法的默认值
方法返回序列的第一个元素,如果未找到任何元素,则返回默认值。在 .NET 6 中,可以重写默认值。您也可以覆盖SingleOrDefault 和 LastOrDefault方法的默认值。
List<int> list1 = new() { 1, 2, 3 }; int item1 = list1.FirstOrDefault(i => i == 4, -1); Console.WriteLine(item1); // -1 List<string> list2 = new() { "Item1" }; string item2 = list2.SingleOrDefault(i => i == "Item2", "Not found"); Console.WriteLine(item2); // Not found
新 *按方法
.NET 6 引入了新的枚举。通过* 方法。提供了一个"键选择器"来比较元素。
新方法:
- MinBy
- MaxBy
- DistinctBy
- ExceptBy
- Intersect
- Union
List<Product> products = new() { new() { Name = "Product1", Price = 100 }, new() { Name = "Product2", Price = 5 }, new() { Name = "Product3", Price = 50 }, }; Product theCheapestProduct = products.MinBy(x => x.Price); Product theMostExpensiveProduct = products.MaxBy(x => x.Price); Console.WriteLine(theCheapestProduct); // Output: Product { Name = Product2, Price = 5 } Console.WriteLine(theMostExpensiveProduct); // Output: Product { Name = Product1, Price = 100 } record Product { public string Name { get; set; } public decimal Price { get; set; } }
新的块方法
如果需要将序列的元素拆分为块,则不必再在 .NET 6 中自行实现它。它引入了一个新的Enumerable.Chunk扩展方法。
IEnumerable<int> numbers = Enumerable.Range(1, 505); IEnumerable<int[]> chunks = numbers.Chunk(100); foreach (int[] chunk in chunks) { Console.WriteLine($"{chunk.First()}...{chunk.Last()}"); } // Output: // 1...100 // 101...200 // 201...300 // 301...400 // 401...500 // 501...505
三向拉链法
Enumerable.Zip扩展方法生成一个元组序列,其中包含来自两个指定序列的元素。在 .NET 6 中,它可以组合来自三个序列的元组。
它不能组合来自四个或更多序列的元组。
int[] numbers = { 1, 2, 3, 4, }; string[] months = { "Jan", "Feb", "Mar" }; string[] seasons = { "Winter", "Winter", "Spring" }; var test = numbers.Zip(months).Zip(seasons); foreach ((int, string, string) zipped in numbers.Zip(months, seasons)) { Console.WriteLine($"{zipped.Item1} {zipped.Item2} {zipped.Item3}"); } // Output: // 1 Jan Winter // 2 Feb Winter // 3 Mar Spring
ElementAt 方法中的索引支持
.NET Core 3.0 引入了Index结构,C# 编译器使用它来支持新的一元前缀"hat"运算符 (^)。它表示"从集合的末尾"索引。在 .NET 6 中,Enumerable.ElementAt方法支持Index。
IEnumerable<int> numbers = new int[] { 1, 2, 3, 4, 5 }; int last = numbers.ElementAt(^0); Console.WriteLine(last); // 5
"取"方法中的范围支持
Range结构已在 .NET Core 3.0 中引入。C# 编译器使用它来支持范围运算符 '..'
在 .NET 6 中,Enumerable.Take方法支持Range。
IEnumerable<int> numbers = new int[] { 1, 2, 3, 4, 5 }; IEnumerable<int> taken1 = numbers.Take(2..4); foreach (int i in taken1) Console.WriteLine(i); // Output: // 3 // 4 IEnumerable<int> taken2 = numbers.Take(..3); foreach (int i in taken2) Console.WriteLine(i); // Output: // 1 // 2 // 3 IEnumerable<int> taken3 = numbers.Take(3..); foreach (int i in taken3) Console.WriteLine(i); // Output: // 4 // 5
使用 TryGetNonEnumeratedCount 避免枚举
.NET 6 引入了一个新的Enumerable.TryGetNonEnumerated方法。它尝试在不强制枚举的情况下确定序列中的元素数。它对于IQueryable非常有用,在调用Enumerable.Count时,您不希望评估整个查询。
IEnumerable<int> numbers = GetNumbers(); TryGetNonEnumeratedCount(numbers); // Output: Could not get a count of numbers without enumerating the sequence IEnumerable<int> enumeratedNumbers = numbers.ToList(); var test = enumeratedNumbers.ElementAt(-1); TryGetNonEnumeratedCount(enumeratedNumbers); // Output: Count: 5 void TryGetNonEnumeratedCount(IEnumerable<int> numbers) { if (numbers.TryGetNonEnumeratedCount(out int count)) Console.WriteLine($"Count: {count}"); else Console.WriteLine("Could not get a count of numbers without enumerating the sequence"); } IEnumerable<int> GetNumbers() { yield return 1; yield return 2; yield return 3; yield return 4; yield return 5; }