C# 元组Tuple使用方法 C#如何使用Tuple和ValueTuple

来源:这里教程网 时间:2026-02-21 17:41:37 作者:

ValueTuple 是 C# 7.0+ 的默认选择,Tuple 已基本弃用

从 C# 7.0 开始,

ValueTuple
成为官方推荐的元组类型:它栈上分配、无装箱开销、支持字段命名、语法简洁;而旧的
Tuple<t1 t2></t1>
是引用类型、不可变、命名只能靠 Item1/Item2,且性能较差。除非维护 .NET Framework 4.6.1 以下老项目,否则一律优先用
ValueTuple

声明和初始化 ValueTuple 的 3 种常用方式

最常用的是字面量语法,编译器自动推导类型并允许命名;也可显式指定泛型类型或用构造函数(极少用):

(int x, string name) person = (25, "Alice");
—— 推导类型 + 自定义字段名,推荐
var point = (10, 20);
—— 匿名字段名(
Item1
,
Item2
),类型由值推断
ValueTuple<string int> t = new("Bob", 30);</string>
—— 显式泛型,仅在泛型约束或反射场景需要

注意:

var
声明时若用字面量,字段名会丢失(
var t = (a: 1, b: "x")
t.a
仍可访问,但类型是匿名元组;真正保留命名需声明具体类型或使用
var
+ 解构)。

解构赋值让 ValueTuple 用起来像普通变量

这是

ValueTuple
最实用的特性之一,避免反复写
t.Item1
t.name

var (age, name) = person;
—— 直接解构成局部变量,类型和名称由元组定义决定
(int a, string n) = person;
—— 显式指定类型,适用于需要强类型转换的场景
方法返回元组时可直接解构:
var (status, msg) = GetResult();

解构要求变量数量、顺序、可隐式转换的类型必须匹配;否则编译报错

CS8135
。不支持跳过某项(如
(_, string n) = t
在 C# 7.0 不合法,C# 7.1+ 才支持弃元
_
)。

ValueTuple 的坑:相等性、序列化与跨 Assembly 兼容性

ValueTuple
重载了
Equals()
GetHashCode()
,按字段值逐个比较,这点比
Tuple<t></t>
更直观;但它不是“纯数据契约”,有几处容易踩雷:

JSON 序列化(如 Newtonsoft.Json)默认不识别命名字段,会序列化成
{"Item1":25,"Item2":"Alice"}
,除非启用
ValueTupleConverter
或用 System.Text.Json(.NET Core 3.0+ 原生支持命名)
跨程序集传递命名元组时,字段名信息只存在于元数据中,接收方若没引用相同版本的
System.ValueTuple
NuGet 包(或目标框架不内置),可能退化为
Item1
访问
ValueTuple
是可变结构体,修改字段(如
t.x = 99
)不会影响其他引用它的变量(因为是值拷贝),这点和很多人直觉不符

如果需要跨服务、存数据库或长期持久化,别依赖

ValueTuple
的字段名——用
record
或自定义
class
更稳妥。

相关推荐