.NET Core 实战 [No.201~207] 元组
元组(Tuple
)类型很早就有了,但在低于 7.0 的版本中,只能通过 Item1、Item2 这样的属性来访问,没有实际的语义。
从 7.0 开始元组增加了语义上的支持等功能,更加易于使用。实际上这里说的元组已经不是指之前的 Tuple
类型了,而是新增的 值元组 ValueTuple
类型。
先说一下旧的元组类型。 Tuple
可以通过 new
关键字 或者 Tuple.Create()
方法 创建,只能通过 Item*
属性获取元素值,而且是只读属性,无法修改。
csharp
var namelessLetters = new Tuple<string, string>("a", "b");
namelessLetters = Tuple.Create("a", "b");
Console.WriteLine($"Item1:{namelessLetters.Item1}, Item2:{namelessLetters.Item2}");
7.0 及之后的几个小版本中对元组添加了很多特性;
新的元组类型 ValueTuple
是值类型,不需要分配堆内存,效率优于 Tuple
。此外,ValueTuple
的元素初始化以后是可以修改的。
ValueTuple
也可以和 Tuple
类似使用 new 关键字 或 ValueTuple.Create()
方法 初始化。不过推荐使用 C# 新语法来初始化,语法上更简洁易懂。
csharp
var namelessLetters = ("a", "b");
namelessLetters.Item1 = "A";
Console.WriteLine($"Item1:{namelessLetters.Item1}, Item2:{namelessLetters.Item2}"); // Item1:A, Item2:b
ValueTuple
支持对元素命名,可以通过如下三种方式声明。
csharp
(string Alpha, string Beta) namedLetters = ("a", "b");
csharp
var namedLetters = (Alpha: "a", Beta: "b");
这第三种是通过 7.1 中新增的推断功能来实现的,需要将项目的语言版本指定为 7.1 或以上。
csharp
var Alpha = "a";
var Beta = "b";
var namedLetters = ( Alpha, Beta );
可以通过指定的元素名获取或修改元素值,同时也仍旧支持使用 Item*
的方式获取或修改元素值。
csharp
namedLetters.Alpha = "A";
Console.WriteLine($"Alpha:{namedLetters.Alpha}, Beta:{namedLetters.Beta}"); // Alpha:A, Beta:b
Console.WriteLine($"Item1:{namedLetters.Item1}, Item2:{namedLetters.Item2}"); // Item1:A, Item2:b
验证下上面定义的 namedLetters 变量的类型。
csharp
Console.WriteLine($"The type of namedLeeters:{namedLetters.GetType()}");
// The type of namedLeeters:System.ValueTuple`2[System.String,System.String]
ValueTuple
支持解构。解构之后,元组中的字段可以作为普通变量来使用。
csharp
(string alpha, string beta) = ("a", "b");
Console.WriteLine($"alpha:{alpha}, beta:{beta}"); // alpha:a, beta:b
解构更常用于的是解构方法返回值中的元组。
csharp
(string Alpha, string Beta) GetLetters()
{
return ("a", "b");
}
csharp
(string alpha, string beta) = GetLetters();
Console.WriteLine($"alpha:{alpha}, beta:{beta}"); // alpha:a, beta:b
当然也可以直接将方法的返回值赋给一个元组变量。
csharp
var letters = GetLetters();
Console.WriteLine($"letters.Alpha:{letters.Alpha}, letters.Beta:{letters.Beta}"); // letters.Alpha:a, letters.Beta:b
另外,自定义类型也可以支持解构,只需要实现 Deconstruct 方法。示例如下:
csharp
public class Point
{
public Point(double x, double y)
=> (X, Y) = (x, y);
public double X { get; }
public double Y { get; }
public void Deconstruct(out double x, out double y) =>
(x, y) = (X, Y);
}
参考:《.NET Core 实战:手把手教你掌握 380 个精彩案例》 -- 周家安 著