在 C# 中,元组和值元组都用于在单个变量中存储多个值。但它们在语法、功能和性能方面存在一些关键差异。
一.Tuples(元组)
元组是一种引用类型,长期以来一直是 .NET 的一部分。它们是使用 System.Tuple 类创建的。
例子
using System;
class Program
{
static void Main()
{
// 创建一个 Tuple 元组
Tuple<int, string, bool> tupleExample = new Tuple<int, string, bool>(1, "Hello", true);
// 访问 Tuple 元素
Console.WriteLine($"Item1: {tupleExample.Item1}, Item2: {tupleExample.Item2}, Item3: {tupleExample.Item3}");
}
}
二.ValueTuples(值元组)
ValueTuples 是最近添加的,是 C# 7.0 引入的值类型。与旧版 System.Tuple 相比,它们更轻量级,性能更好。ValueTuple 是使用 System.ValueTuple 结构创建的。
例子
class Program
{
static void Main()
{
// 创建一个 ValueTuple
(int, string, bool) valueTuple = (1, "Hello", true);
// 访问 ValueTuple 的元素
Console.WriteLine($"Item1: {valueTuple.Item1}, Item2: {valueTuple.Item2}, Item3: {valueTuple.Item3}");
// 为 ValueTuple 的元素分配名称
var namedValueTuple = (Id: 1, Message: "Hello", IsActive: true);
Console.WriteLine($"Id: {namedValueTuple.Id}, Message: {namedValueTuple.Message}, IsActive: {namedValueTuple.IsActive}");
}
}
三.主要区别
- Tuples(元组):引用类型(System.Tuple)。
- ValueTuples(值元组):值类型(System.ValueTuple)。
- Tuples(元组):由于引用类型和堆分配而速度较慢。
- ValueTuples(值元组):由于值类型和堆栈分配而速度更快。
- Tuples(元组):需要一个新的关键字。
- ValueTuples(值元组):简洁,更易读,可以使用解构和命名元素。
- Tuples(元组):不可变值,创建后无法更改。
- ValueTuples(值元组):可变值可以在创建后更改。
四.实际场景
在从 SQL Server 数据库检索数据的实际场景中,使用Tuple 和 ValueTuple。
1.执行以下 SQL Server 脚本
CREATE TABLE EmployeesDetails (
Id INT PRIMARY KEY,
Name NVARCHAR(100),
IsActive BIT
);
INSERT INTO EmployeesDetails (Id, Name, IsActive)
VALUES (1, 'Alice', 1);
INSERT INTO EmployeesDetails (Id, Name, IsActive)
VALUES (2, 'Bob', 0);
2.查询
3.创建如下类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
namespace WpfApp2
{
public class TupleExamples
{
static string connectionString = "Server=DESKTOP-JNM9BF1\\OMatrixtechSERVER;Database=Demo;User Id=sa;Password=1234;"; // 设置数据库连接字符串
static string query = "SELECT Id, Name, IsActive FROM EmployeesDetails"; // 定义查询语句,用于从 EmployeesDetails 表中获取数据
// 方法:从数据库中检索员工详情,并以 Tuple 的形式返回
public static Tuple<int, string, bool> GetEmployeeTupleResult()
{
using (SqlConnection connection = new SqlConnection(connectionString)) // 使用连接字符串创建数据库连接
{
SqlCommand command = new SqlCommand(query, connection); // 创建 SqlCommand 对象,执行查询
connection.Open(); // 打开数据库连接
SqlDataReader reader = command.ExecuteReader(); // 执行查询并返回 SqlDataReader 对象
if (reader.Read()) // 如果有数据返回
{
return new Tuple<int, string, bool>( // 创建一个 Tuple 对象并返回,包含三个字段的值
reader.GetInt32(0), // 从结果中获取第一个字段(Id)
reader.GetString(1), // 从结果中获取第二个字段(Name)
reader.GetBoolean(2) // 从结果中获取第三个字段(IsActive)
);
}
}
return null; // 如果没有数据返回,返回 null
}
// 方法:从数据库中检索员工详情,并以 ValueTuple 的形式返回
public static (int Id, string Name, bool IsActive) GetEmployeeValueTupleResult()
{
using (SqlConnection connection = new SqlConnection(connectionString)) // 使用连接字符串创建数据库连接
{
SqlCommand command = new SqlCommand(query, connection); // 创建 SqlCommand 对象,执行查询
connection.Open(); // 打开数据库连接
SqlDataReader reader = command.ExecuteReader(); // 执行查询并返回 SqlDataReader 对象
if (reader.Read()) // 如果有数据返回
{
return ( // 返回一个命名的 ValueTuple,包含三个字段的值
reader.GetInt32(0), // 从结果中获取第一个字段(Id)
reader.GetString(1), // 从结果中获取第二个字段(Name)
reader.GetBoolean(2) // 从结果中获取第三个字段(IsActive)
);
}
}
return (0, null, false); // 如果没有数据返回,返回一个默认的 ValueTuple
}
}
}
// 示例:如何调用上述方法以检索并显示员工详情
private void ValueTuple_Click(object sender, RoutedEventArgs e) // 按钮点击事件处理程序
{
Tuple<int, string, bool> tupleValue = TupleExamples.GetEmployeeTupleResult(); // 调用 GetEmployeeTupleResult 方法,并将结果存储在 tupleValue 变量中
(int Id, string Name, bool IsActive) = TupleExamples.GetEmployeeValueTupleResult(); // 调用 GetEmployeeValueTupleResult 方法,并将 ValueTuple 的结果解构到相应的变量中
}
五.结论
ValueTuple 是大多数当代 C# 应用程序的首选,因为它具有性能优势和更简洁的语法。虽然传统 Tuple 仍然可以访问和使用,但除非需要与旧版 .NET 兼容,否则它通常不那么受欢迎。