C Sharp LINQ 转换
外观
C# LINQ 转换[编辑 | 编辑源代码]
LINQ(Language Integrated Query)是 C# 中强大的查询语言集成功能,而 LINQ 转换 是指将数据从一种形式转换为另一种形式的过程。转换操作在数据处理中非常常见,例如将集合类型转换、投影数据或重新组织数据以满足特定需求。
介绍[编辑 | 编辑源代码]
LINQ 转换操作允许开发者以声明式的方式对数据进行转换,而无需编写复杂的循环或条件语句。常见的转换操作包括:
- Select:将数据投影为新的形式。
- Cast 和 OfType:转换集合中的元素类型。
- ToArray、ToList、ToDictionary、ToLookup:将查询结果转换为特定集合类型。
- AsEnumerable 和 AsQueryable:改变查询的执行方式。
这些操作使得数据处理更加灵活和高效,适用于各种数据源,包括内存集合、数据库和 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 转换[编辑 | 编辑源代码]
Cast 和 OfType 用于将集合中的元素转换为指定类型,但它们的处理方式不同:
- 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` 等方法,开发者可以轻松地将数据从一种形式转换为另一种形式,提高代码的可读性和效率。