在 .NET 9 中,LINQ (Language Integrated Query) 引入了一些新的功能和改进,使得开发者可以更加灵活和高效地处理集合数据。以下是一些主要的新增功能,并提供了实操示例。

1. FirstOrDefaultAsync 和 SingleOrDefaultAsync 方法(异步扩展)

在 .NET 9 中,LINQ 扩展方法新增了异步版本的 FirstOrDefaultSingleOrDefault。这些方法用于从集合中获取符合条件的元素,特别适用于异步操作,比如访问数据库时的查询。

示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        var data = new List<int> { 1, 2, 3, 4, 5 };

        // 使用 FirstOrDefaultAsync 来异步获取第一个符合条件的元素
        var first = await data.AsQueryable().FirstOrDefaultAsync(x => x > 3);
        Console.WriteLine(first);  // 输出: 4

        // 使用 SingleOrDefaultAsync 来异步获取符合条件的唯一元素
        var single = await data.AsQueryable().SingleOrDefaultAsync(x => x == 4);
        Console.WriteLine(single);  // 输出: 4
    }
}

在这个例子中,AsQueryable() 将列表转换为可以执行 LINQ 查询的 IQueryable,并且可以使用异步方法 FirstOrDefaultAsyncSingleOrDefaultAsync 进行查询。

2. ToListAsync 和 ToArrayAsync

与前述方法类似,ToListAsyncToArrayAsync 也是用于异步获取列表或数组的新方法。它们常用于需要从数据库或其他异步数据源获取数据时。

示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        var data = new List<int> { 1, 2, 3, 4, 5 };

        // 使用 ToListAsync 来异步获取列表
        var list = await data.AsQueryable().Where(x => x > 2).ToListAsync();
        Console.WriteLine(string.Join(", ", list));  // 输出: 3, 4, 5

        // 使用 ToArrayAsync 来异步获取数组
        var array = await data.AsQueryable().Where(x => x < 4).ToArrayAsync();
        Console.WriteLine(string.Join(", ", array));  // 输出: 1, 2, 3
    }
}

3. GroupBy 中的新 By 方法(增强的分组功能)

.NET 9 引入了增强版的 GroupBy,可以直接在 GroupBy 中使用 By 子句来对集合进行分组,并且可以指定更多灵活的分组条件。

示例:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var people = new List<(string Name, int Age)>
        {
            ("Alice", 30),
            ("Bob", 25),
            ("Charlie", 30),
            ("David", 25),
            ("Eva", 35)
        };

        var grouped = people.GroupBy(x => x.Age).ToList();

        foreach (var group in grouped)
        {
            Console.WriteLine($"Age: {group.Key}");
            foreach (var person in group)
            {
                Console.WriteLine($"  {person.Name}");
            }
        }
    }
}

输出:

Age: 30
  Alice
  Charlie
Age: 25
  Bob
  David
Age: 35
  Eva

4. DistinctBy 和 ThenBy

在 LINQ 中新增了 DistinctByThenBy,它们增强了集合去重和排序的功能。

  • DistinctBy: 用于按某个键去重。
  • ThenBy: 用于在 OrderBy 之后进行次级排序。

示例:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var people = new List<(string Name, int Age)>
        {
            ("Alice", 30),
            ("Bob", 25),
            ("Alice", 30),
            ("Charlie", 30),
            ("David", 25),
            ("Eva", 35)
        };

        // 使用 DistinctBy 来去重
        var distinctPeople = people.DistinctBy(p => p.Name).ToList();
        foreach (var person in distinctPeople)
        {
            Console.WriteLine($"{person.Name} - {person.Age}");
        }
        
        // 使用 ThenBy 进行多级排序
        var sortedPeople = people.OrderBy(p => p.Age).ThenBy(p => p.Name).ToList();
        foreach (var person in sortedPeople)
        {
            Console.WriteLine($"{person.Name} - {person.Age}");
        }
    }
}

5. IntersectBy 和 ExceptBy

IntersectByExceptBy 是新的 LINQ 扩展方法,用于比较两个集合并基于某个键选择交集或差集。

  • IntersectBy: 从集合中选择与另一个集合的交集。
  • ExceptBy: 从集合中选择与另一个集合的差集。

示例:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var collection1 = new List<(string Name, int Age)>
        {
            ("Alice", 30),
            ("Bob", 25),
            ("Charlie", 30),
            ("David", 25)
        };

        var collection2 = new List<(string Name, int Age)>
        {
            ("Alice", 30),
            ("David", 25)
        };

        // 使用 IntersectBy 获取交集
        var intersection = collection1.IntersectBy(collection2.Select(p => p.Name), p => p.Name).ToList();
        foreach (var person in intersection)
        {
            Console.WriteLine($"{person.Name} - {person.Age}");
        }

        // 使用 ExceptBy 获取差集
        var difference = collection1.ExceptBy(collection2.Select(p => p.Name), p => p.Name).ToList();
        foreach (var person in difference)
        {
            Console.WriteLine($"{person.Name} - {person.Age}");
        }
    }
}

总结

.NET 9 对 LINQ 做了许多增强和扩展,尤其是在异步支持、去重、分组、排序等方面。通过这些新功能,开发者可以更加高效、灵活地处理数据。