C# - ValueTuple
C# 7.0 (.NET Framework 4.7) 引入了 ValueTuple
结构,它是 Tuple 的值类型表示。
ValueTuple 仅在 .NET Framework 4.7 中可用。如果您的项目中没有看到 ValueTuple,则需要安装 ValueTuple。(.NET Framework 4.7 或更高版本,或 .NET Standard Library 2.0 或更高版本已包含 ValueTuple。)
要安装 ValueTuple 包,请在解决方案资源管理器中右键单击项目并选择 管理 NuGet 包...。这将打开 NuGet 包管理器。单击 浏览 选项卡,在搜索框中搜索 ValueTuple,然后选择 System.ValueTuple 包,如下图所示。

ValueTuple 初始化
创建和初始化 ValueTuple
非常简单。可以使用括号 ()
并指定其中的值来创建和初始化。
var person = (1, "Bill", "Gates");
//equivalent Tuple
//var person = Tuple.Create(1, "Bill", "Gates");
ValueTuple
也可以通过指定每个元素的类型来初始化,如下图所示。
(int, string, string) person = (1, "Bill", "Gates");
person.Item1; // returns 1
person.Item2; // returns "Bill"
person.Item3; // returns "Gates"
以下是为每个成员声明类型的简写方式。
(int, string, string) person = (1, "James", "Bond");
person.Item1; // returns 1
person.Item2; // returns "James"
person.Item3; // returns "Bond"
请注意,我们在上面的元组初始化语句中没有使用 var
;相反,我们在括号内提供了每个成员值的类型。
Tuple 需要至少两个值。以下不是元组。
var number = (1); // int type, NOT a tuple
var numbers = (1,2); //valid tuple
与 Tuple
不同,ValueTuple
可以包含八个以上的值。
var numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
命名成员
我们可以为 ValueTuple
属性分配名称,而不是使用默认属性名称(如 Item1、Item2 等)。
(int Id, string FirstName, string LastName) person = (1, "Bill", "Gates");
person.Id; // returns 1
person.FirstName; // returns "Bill"
person.LastName; // returns "Gates"
我们也可以在右侧为值分配成员名称,如下所示。
var person = (Id:1, FirstName:"Bill", LastName: "Gates");
请注意,我们可以在左侧或右侧提供成员名称,但不能同时在两侧提供。左侧优先于右侧。以下将忽略右侧的名称。
// PersonId, FName, LName will be ignored.
(int Id, string FirstName, string LastName) person = (PersonId:1, FName:"Bill", LName: "Gates");
// PersonId, FirstName, LastName will be ignored. It will have the default names: Item1, Item2, Item3.
(string, string, int) person = (PersonId:1, FName:"Bill", LName: "Gates");
我们也可以将变量作为成员值进行分配。
string firstName = "Bill", lastName = "Gates";
var person = (FirstName: firstName, LastName: lastName);
ValueTuple 作为参数
ValueType 也可以是方法的参数类型或返回类型。以下方法接受一个 ValueTuple
类型参数。
static void Main(string[] args)
{
DisplayTuple((1, "Bill", "Gates"));
}
static void DisplayTuple((int, string, string) person)
{
Console.WriteLine("{0}, {1}, {2}", person.Item1, person.Item2, person.Item3);
}
以下方法从方法返回一个 ValueTuple。
以下方法从方法返回一个 ValueTuple。
static void Main(string[] args)
{
var person = GetPerson();
Console.WriteLine("{0}, {1}, {2}", person.Item1, person.Item2, person.Item3);
}
static (int, string, string) GetPerson()
{
return (1, "Bill", "Gates");
}
您还可以为从方法返回的 ValueTuple
指定成员名称。
static void Main(string[] args)
{
var person = GetPerson();
Console.WriteLine("{0}, {1}, {2}", person.Id, person.FirstName, person.LastName);
}
static (int Id, string FirstName, string LastName) GetPerson()
{
return (Id:1, FirstName: "Bill", LastName: "Gates");
}
解构
可以通过解构 ValueTuple
来检索其单个成员。解构声明语法将 ValueTuple
分解为其各个部分,并将这些部分单独分配给新的变量。
static void Main(string[] args)
{
// change property names
(int PersonId, string FName, string LName) = GetPerson();
}
static (int, string, string) GetPerson()
{
return (Id:1, FirstName: "Bill", LastName: "Gates");
}
我们也可以使用 var 代替显式数据类型名称。
static void Main(string[] args)
{
// use var as datatype
(var PersonId, var FName, var LName) = GetPerson();
}
static (int, string, string) GetPerson()
{
return (Id:1, FirstName: "Bill", LastName: "Gates");
}
ValueTuple
还允许在解构中对您不打算使用的成员使用“丢弃”。
// use discard _ for the unused member LName
(var id, var FName, _) = GetPerson();