C# 元组的用法
目录
一、值元组 System.ValueTuple
创建元组
命名元组元素
解构元组
元组的比较
元组的可变性
作为方法的返回值
二、传统元组 System.Tuple
Tuple.Create 方法
元组的不可变性
作为方法的返回值
一、值元组 System.ValueTuple
值类型,由 C# 7.0 引入,语法更简洁,性能更高。
创建元组
案例:
var tuple = (1, "Hello", 3.14); // 创建一个元组,包含 int, string, double 三个类型的值
Console.WriteLine(tuple.Item1); // 输出 1
Console.WriteLine(tuple.Item2); // 输出 Hello
Console.WriteLine(tuple.Item3); // 输出 3.14
在这里使用了 var,那么它原本的类型是怎么定义的呢?如下:
(int, string, double) tuple = (1, "Hello", 3.14); // 创建一个元组,包含 int, string, double 三个类型的值
Console.WriteLine(tuple.Item1); // 输出 1
Console.WriteLine(tuple.Item2); // 输出 Hello
Console.WriteLine(tuple.Item3); // 输出 3.14
这么看,使用 var 确实方便不少。
当然你也能把它用在字典中、List 中,等等。
案例:
var dictionary = new Dictionary<string, (int, float)>()
{{"a", (1, 1.5f) },{"b", (3, 5.8f) }
};
var list = new List<(int, string)>
{(2, "Bob"),(1, "Alice"),(3, "Charlie")
};
在 .NET8 中,还可以用在 switch 中,
案例:
public static string GetRole((int, string) person)
{switch (person){case (1, "Alice"):return "Developer";case (2, "Bob"):return "Manager";default:return "Unknown";}
}var person = (1, "Alice");
Console.WriteLine(GetRole(person)); // 输出 Developer
命名元组元素
你可以为元组中的元素指定名称,来提高可读性。
案例:
var tuple = (Id: 1, Name: "Alice", Age: 25);
Console.WriteLine(tuple.Id); // 输出 1
Console.WriteLine(tuple.Name); // 输出 Alice
Console.WriteLine(tuple.Age); // 输出 25
这么写也是没有任何问题的,和 类[] 这种写法差不多
var data = new[]
{new { Name = "Alice", Age = 30 },new { Name = "Bob", Age = 25 },new { Name = "Charlie", Age = 35 }
};
解构元组
C# 7.0 引入了元组的解构语法,你可以将元组的值直接赋给单独的变量。
案例1:
var (id, name, age) = (1, "Alice", 25); // 解构元组
Console.WriteLine(id); // 输出 1
Console.WriteLine(name); // 输出 Alice
Console.WriteLine(age); // 输出 25
直接使用 tuple.Item1,tuple.Item2 这种写法确实是方便一些,但自己定义它变量会看起来更加直观一些。
案例2:
// 定义一个包含两个元素的元组
(int id, string name) = (1, "Alice");// 访问元组的元素
Console.WriteLine(id); // 输出:1
Console.WriteLine(name); // 输出:Alice// 使用解构赋值
var (id2, name2) = (2, "Bob");
Console.WriteLine(id2); // 输出:2
Console.WriteLine(name2); // 输出:Bob
元组的比较
它和普通的值类型一样,也是可以使用 == 来判断是否相同
案例:
var tuple1 = (1, "Alice");
var tuple2 = (1, "Alice");
var tuple3 = (2, "Bob");Console.WriteLine(tuple1 == tuple2); // 输出 True
Console.WriteLine(tuple1 == tuple3); // 输出 False
元组的可变性
这和后面的章节 System.Tuple 不可变性有所不同,System.ValueTuple 是可以修改元组的值。
案例:
var tuple = (1, "Alice", 25);
tuple.Item1 = 30;
这段代码是不会报错的,并且能正确的输出它的值
Console.WriteLine(tuple.Item1); // 输出:30
作为方法的返回值
这和后面的章节 System.Tuple 用法差不多
案例:
public static (int, string) GetPersonInfo()
{return (42, "Alice");
}var result = GetPersonInfo();
Console.WriteLine($"Id: {result.Item1}, Name: {result.Item2}");
用在异步编程中也是一样的,我经常这么干
public static async Task<(int, string)> GetDataAsync()
{await Task.Delay(1000); // 模拟异步操作return (42, "Hello");
}
二、传统元组 System.Tuple
引用类型,首次在 .NET Framework2.0 被引入,主要用于支持 F# 的元组类型。此时它并非通用语言运行时(CLR)的标准库类型,其他 .NET 语言(如 C#)无法直接使用,从 .NET Framework 4.0 开始,System.Tuple 被正式引入到 Base Class Library (BCL) 中,成为所有 .NET 语言通用的元组实现
Tuple.Create 方法
Tuple.Create 是一个静态方法,用于创建一个元组实例,它可以接受不同数量和类型的参数。通过 Tuple.Create 方法,C# 会自动推断每个元素的类型,因此你不需要显式地指定类型。
Tuple 最多能存储8个元素。
案例:
var tuple = Tuple.Create(true, "Hello", "World");
Console.WriteLine(tuple.Item1); // 输出 true
Console.WriteLine(tuple.Item2); // 输出 Hello
Console.WriteLine(tuple.Item3); // 输出 World
这里使用 var 确实方便很多,不用每次去定义它原本的写法,比如
Tuple<bool, string, string> tuple = Tuple.Create(true, "Hello", "World");
Console.WriteLine(tuple.Item1); // 输出 true
Console.WriteLine(tuple.Item2); // 输出 Hello
Console.WriteLine(tuple.Item3); // 输出 World
使用构造函数
var tuple = new ValueTuple<int, string>(1, "Hello");
但是,如果值是一些不确定的情况,也会报错,比如值为 null
如果非要传一个 null 的话也是可以的,只是要定义这个值原本的类型,比如:
var tuple = Tuple.Create<bool, string>(false, null);
这样子就不会报错了。
元组的不可变性
Tuple 类是不可变的,这意味着一旦创建了元组,其元素的值就不能修改
案例:
作为方法的返回值
如果想同时返回2个或者多个值,又不想去写一个类,元组是一个好的替代方案
internal class Test
{public Tuple<bool, string> hello(){return Tuple.Create(true, string.Empty);}
}
end