跳转到内容

C Sharp LINQ 转换

来自代码酷

C# LINQ 转换[编辑 | 编辑源代码]

LINQ(Language Integrated Query)是 C# 中强大的查询语言集成功能,而 LINQ 转换 是指将数据从一种形式转换为另一种形式的过程。转换操作在数据处理中非常常见,例如将集合类型转换、投影数据或重新组织数据以满足特定需求。

介绍[编辑 | 编辑源代码]

LINQ 转换操作允许开发者以声明式的方式对数据进行转换,而无需编写复杂的循环或条件语句。常见的转换操作包括:

  • Select:将数据投影为新的形式。
  • CastOfType:转换集合中的元素类型。
  • ToArrayToListToDictionaryToLookup:将查询结果转换为特定集合类型。
  • AsEnumerableAsQueryable:改变查询的执行方式。

这些操作使得数据处理更加灵活和高效,适用于各种数据源,包括内存集合、数据库和 XML。

Select 转换[编辑 | 编辑源代码]

Select 是最常用的转换操作,它允许对集合中的每个元素应用一个转换函数,生成一个新的序列。

示例代码[编辑 | 编辑源代码]

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

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        
        // 将每个数字转换为它的平方
        var squares = numbers.Select(x => x * x);
        
        Console.WriteLine("原始数据: " + string.Join(", ", numbers));
        Console.WriteLine("转换后的数据: " + string.Join(", ", squares));
    }
}

输出[编辑 | 编辑源代码]

原始数据: 1, 2, 3, 4, 5
转换后的数据: 1, 4, 9, 16, 25

解释

  • 使用 `Select` 方法,传入一个 Lambda 表达式 `x => x * x`,对每个元素进行平方运算。
  • 结果是一个新的 `IEnumerable<int>`,包含转换后的数据。

Cast 和 OfType 转换[编辑 | 编辑源代码]

CastOfType 用于将集合中的元素转换为指定类型,但它们的处理方式不同:

  • Cast:尝试将所有元素转换为目标类型,如果失败则抛出异常。
  • OfType:仅返回可以转换为目标类型的元素,忽略其他元素。

示例代码[编辑 | 编辑源代码]

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

class Program
{
    static void Main()
    {
        ArrayList mixedList = new ArrayList { 1, "two", 3, "four", 5.0 };
        
        // 使用 Cast 转换(会抛出异常,因为包含非 int 类型)
        try
        {
            var castNumbers = mixedList.Cast<int>();
            Console.WriteLine("Cast 结果: " + string.Join(", ", castNumbers));
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Cast 失败:包含无法转换为 int 的元素。");
        }
        
        // 使用 OfType 转换(仅返回 int 类型元素)
        var ofTypeNumbers = mixedList.OfType<int>();
        Console.WriteLine("OfType 结果: " + string.Join(", ", ofTypeNumbers));
    }
}

输出[编辑 | 编辑源代码]

Cast 失败:包含无法转换为 int 的元素。
OfType 结果: 1, 3

解释

  • `Cast<int>()` 尝试将所有元素转换为 `int`,但由于包含字符串和浮点数,抛出异常。
  • `OfType<int>()` 仅返回可以安全转换为 `int` 的元素(1 和 3)。

集合类型转换[编辑 | 编辑源代码]

LINQ 提供多种方法将查询结果转换为特定集合类型:

  • ToArray:转换为数组。
  • ToList:转换为列表。
  • ToDictionary:转换为字典。
  • ToLookup:转换为分组查找结构。

示例代码[编辑 | 编辑源代码]

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

class Program
{
    static void Main()
    {
        var numbers = Enumerable.Range(1, 5);
        
        // 转换为数组
        int[] array = numbers.ToArray();
        Console.WriteLine("数组: " + string.Join(", ", array));
        
        // 转换为列表
        List<int> list = numbers.ToList();
        Console.WriteLine("列表: " + string.Join(", ", list));
        
        // 转换为字典(键为数字,值为平方)
        Dictionary<int, int> dictionary = numbers.ToDictionary(x => x, x => x * x);
        Console.WriteLine("字典:");
        foreach (var kvp in dictionary)
        {
            Console.WriteLine($"{kvp.Key} -> {kvp.Value}");
        }
    }
}

输出[编辑 | 编辑源代码]

数组: 1, 2, 3, 4, 5
列表: 1, 2, 3, 4, 5
字典:
1 -> 1
2 -> 4
3 -> 9
4 -> 16
5 -> 25

解释

  • `ToArray` 和 `ToList` 分别将查询结果转换为数组和列表。
  • `ToDictionary` 接受两个 Lambda 表达式:一个定义键,一个定义值。

AsEnumerable 和 AsQueryable[编辑 | 编辑源代码]

这两个方法用于改变查询的执行方式:

  • AsEnumerable:强制后续操作在内存中执行(适用于数据库查询的客户端处理)。
  • AsQueryable:将内存集合转换为 `IQueryable`,以便后续操作转换为 SQL(适用于 Entity Framework)。

示例代码[编辑 | 编辑源代码]

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

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        
        // 转换为 IQueryable(适用于 EF Core)
        var queryable = numbers.AsQueryable();
        var filtered = queryable.Where(x => x % 2 == 0);
        Console.WriteLine("AsQueryable 结果: " + string.Join(", ", filtered));
        
        // 转换为 IEnumerable(强制客户端处理)
        var enumerable = numbers.AsEnumerable();
        var squared = enumerable.Select(x => x * x);
        Console.WriteLine("AsEnumerable 结果: " + string.Join(", ", squared));
    }
}

输出[编辑 | 编辑源代码]

AsQueryable 结果: 2, 4
AsEnumerable 结果: 1, 4, 9, 16, 25

解释

  • `AsQueryable` 适用于需要将查询转换为 SQL 的场景(如数据库查询)。
  • `AsEnumerable` 强制后续操作在客户端执行。

实际应用案例[编辑 | 编辑源代码]

假设我们有一个学生列表,需要将其转换为不同的数据结构以满足业务需求:

场景描述[编辑 | 编辑源代码]

  • 将学生姓名转换为大写。
  • 按年龄分组。
  • 转换为字典(学号为键)。

示例代码[编辑 | 编辑源代码]

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

class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Id = 1, Name = "Alice", Age = 20 },
            new Student { Id = 2, Name = "Bob", Age = 22 },
            new Student { Id = 3, Name = "Charlie", Age = 20 }
        };
        
        // 转换姓名为大写
        var upperCaseNames = students.Select(s => s.Name.ToUpper());
        Console.WriteLine("大写姓名: " + string.Join(", ", upperCaseNames));
        
        // 按年龄分组
        var groupedByAge = students.GroupBy(s => s.Age);
        Console.WriteLine("按年龄分组:");
        foreach (var group in groupedByAge)
        {
            Console.WriteLine($"年龄 {group.Key}: {string.Join(", ", group.Select(s => s.Name))}");
        }
        
        // 转换为字典(学号为键)
        var studentDict = students.ToDictionary(s => s.Id, s => s.Name);
        Console.WriteLine("学号字典:");
        foreach (var kvp in studentDict)
        {
            Console.WriteLine($"{kvp.Key} -> {kvp.Value}");
        }
    }
}

输出[编辑 | 编辑源代码]

大写姓名: ALICE, BOB, CHARLIE
按年龄分组:
年龄 20: Alice, Charlie
年龄 22: Bob
学号字典:
1 -> Alice
2 -> Bob
3 -> Charlie

解释

  • `Select` 用于投影数据(姓名转大写)。
  • `GroupBy` 用于分组(按年龄)。
  • `ToDictionary` 用于创建学号到姓名的映射。

总结[编辑 | 编辑源代码]

LINQ 转换操作是数据处理的核心工具,能够以简洁的方式完成复杂的数据转换任务。通过 `Select`、`Cast`、`ToArray` 等方法,开发者可以轻松地将数据从一种形式转换为另一种形式,提高代码的可读性和效率。