优先提示:C# 值元组(ValueTuple)值类型元组,也是元组,可以更好的与C# 7.0之前版本的元组(Value)区别。标题号(4-12)上篇和本篇这两篇我认为应该放到同等位置学习,两个都学或者任选其一均可。
C#7.0(.NET Framework 4.7)引入了 ValueTuple 结构,即新的元组类型,称为“值元组”(Value Tuples)。值元组是更为轻量级和高效的数据结构,可以用于更多的场景。它是元组的值类型表示。值元组使用括号和逗号来定义元素,而不是使用Tuple类。例如,(int, string)表示一个包含一个整数和一个字符串的值元组。值元组还支持解构赋值,可以方便地将值元组的值赋给单独的变量。
该元组类型是值类型;元组元素是公共字段。 这使得元组为可变的值类型。
区别
c#元组 7.0之前版本和7.0后的版本区别:
在C# 7.0之前的版本中,可以使用Tuple类来创建元组。Tuple类位于System命名空间中,具有多个泛型重载,用于创建不同数量和类型的元组。例如,Tuple<T1>表示一个包含一个元素的元组,Tuple<T1, T2>表示一个包含两个元素的元组,以此类推。
在C# 7.0及之后的版本中,引入了新的元组类型,称为“值元组”(Value Tuples)。值元组是更为轻量级和高效的数据结构,可以用于更多的场景。值元组使用括号和逗号来定义元素,而不是使用Tuple类。例如,(int, string)表示一个包含一个整数和一个字符串的值元组。
值元组还支持解构赋值,可以方便地将值元组的值赋给单独的变量。
此外,值元组还引入了新的语法和特性,例如可以使用Item1、Item2等属性来访问元组中的元素,而不需要指定具体的类型。同时,值元组还支持匿名类型的创建和转换,可以更方便地处理数据。
C#中的元组和值元组的区别:
C#中的元组和值元组都是用于存储一组数据的结构,但它们有一些重要的区别。
- 类型不同:元组是引用类型,而值元组是值类型。
- 用途不同:元组通常用于在程序中传递数据,而值元组主要用于在表达式中创建和分解数据。
- 可变性不同:元组是不可变的,一旦创建就无法修改其中的元素,而值元组是可变的,可以修改其中的元素值。
- 数据成员不同:元组的数据成员是属性,而值元组的数据成员是字段。
- 性能不同:值元组相对于元组来说更加轻量级和高效,因为它在内存中占用的空间较小,而且可以避免引用类型的开销。
- 语法不同:元组使用Tuple类和属性来定义和访问元素,而值元组使用括号和逗号来定义和访问元素。
区别示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ValueTupleType
{
internal class Program
{
static void Main(string[] args)
{
var student1 = (1, "ZhangSan", "HeNan",68,78,80,98,76,88,89,66);//c#7.0之后的版本
var student2 = Tuple.Create("WangWu", 26, "HeBei", 68, 78, 80, 98, 76);//c#7.0之前的版本//c#7.0之前的版本
// 访问元组中的元素
Console.WriteLine(student1);//输出当前元组
Console.WriteLine("----------------------------------------------------");
Console.WriteLine("类型为: "+student1.GetType());//获取类型
Console.WriteLine("----------------------------------------------------");
Console.WriteLine("ID:"+student1.Item1);//访问元组元素
Console.WriteLine("Name:" + student1.Item2);
Console.WriteLine("ADD:" + student1.Item3);
Console.WriteLine(student1.Item10);
Console.WriteLine("----------------------------------------------------");
Console.WriteLine();
Console.WriteLine("Name2:" + student2.Item1 + "\n" + "Address:" + student2.Item3 + "\n" + "Age:" + student2.Item2);//访问元组元素
}
}
}
下面正式开始介绍C# 值元组(ValueTuple):
语法:
(Type1 item1, Type2 item2, ...)
Type1、Type2等表示元素的数据类型,item1、item2等表示元素的名称。元素之间使用逗号进行分隔,整个值元组使用括号包裹。
示例代码:
var student1 = (1, "ZhangSan", "HeNan",68,78,80,98,76,88,89,66);//c#7.0之后的版本
(int, string, int, double, float,decimal) student3 = (1,"2",3,4.01,5.166666f,12.02M);
创建一个包含三个元素的元组示例:
var student1 = (1, "ZhangSan", "HeNan");
ValueTuple初始化
创建和初始化 ValueTuple ,可以使用括号()并在其中指定值来创建和初始化它。
var person = (1, "ZhangSan", "HeNan");
//等效元组
var person = Tuple.Create(1, "ZhangSan", "HeNan");
通过指定各元素的类型初始化 ValueTuple.
ValueTuple<int, string, string> person = (1, "ZhangSan", "HeNan");
Console.WriteLine(person.Item1); // 返回1
Console.WriteLine(person.Item2); // 返回 "ZhangSan"
Console.WriteLine(person.Item3); // 返回 "HeNan"
为每个成员声明类型的简写方法.
(int, string, string) person = (1, "ZhangSan", "HeNan");
Console.WriteLine(person.Item1); // 返回1
Console.WriteLine(person.Item2); // 返回 "ZhangSan"
Console.WriteLine(person.Item3); // 返回 "HeNan"
请仔细观察上面的写法,并没有在上面的 tuple 初始化语句中使用 var ,相反我们在括号中提供了每个成员值的类型。
元组至少需要两个值:
var number = (1); // int类型,不是元组
var numbers = (1,2); // 有效元组
与 Tuple 不同,ValueTuple 可以包含八个以上的值。
var numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15,16);//比较多
命名成员
可以为ValueTuple属性分配名称,而不是使用默认属性名称,例如Item1,Item2等。
(int Id, string Name, string Add) person = (1, "ZhangSan", "HeNan");
Console.WriteLine(person.Id); // 返回1
Console.WriteLine(person.Name); // 返回 "ZhangSan"
Console.WriteLine(person.Add); // 返回 "HeNan"
我们还可以在右侧为成员名称分配值,如下所示。
var person = (Id:1, Name:"ZhangSan",Add: "HeNan");
请注意,可以在左侧或右侧提供成员名称,但不能在两侧提供成员名称。左侧优先于右侧。以下内容将忽略右侧的名称。
// PersonId,Name,Add将被忽略。
(int Id, string Name, string Add) person = (PersonId:1, Name:"ZhangSan", Add: "HeNan");
// PersonId,Name,Add将被忽略。。它将具有默认名称:Item1,Item2,Item3。
(string, string, int) person = (PersonId:1, Name:"ZhangSan", Add: "HeNan");
还可以将变量分配为成员值。
string Name = "ZhangSan", Add = "HeNan";
var per = (Name: name, Add: add);
声明元组变量、对它进行初始化并访问其数据成员:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ValueTupleType
{
internal class Program
{
static void Main(string[] args)
{
var student1 = (1, "ZhangSan", "HeNan");//c#7.0之后的版本
// 访问元组中的元素
Console.WriteLine("类型为: "+student1.GetType());//获取类型
Console.WriteLine("----------------------------------------------------");
Console.WriteLine("ID:"+student1.Item1);//访问元组元素
Console.WriteLine("Name:" + student1.Item2);
Console.WriteLine("ADD:" + student1.Item3);
}
}
}
ValueTuple作为返回类型:
完整示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ValueTupleType3
{
internal class Program
{
static void Main(string[] args)
{
DisplayTuple((1, "ZhangSan", "HeNan"));
}
static void DisplayTuple((int, string, string) person)
{
Console.WriteLine(#34;Id = {person.Item1}");
Console.WriteLine(#34;Name = {person.Item2}");
Console.WriteLine(#34;Address = {person.Item3}");
}
}
}
解构
在 C# 中,解构(deconstruction)是一种将复合数据类型(例如元组、数组、集合等)分解为单独的变量或组件的过程。解构声明语法将 ValueTuple 拆分为多个部分,并分别将这些部分分配给新变量,解构可以使代码更加简洁和易于阅读,同时提高代码的可读性和可维护性。
带“解构”赋值的值元组使用示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace ValueTupleType2
{
internal class Program
{
static void Main(string[] args)
{
// 创建一个值元组
var student = (Name: "ZhangSan", Age: 28, Major: "Computer Science");
// 访问值元组中的元素
Console.WriteLine(#34;Name: {student.Name}");
Console.WriteLine(#34;Age: {student.Age}");
Console.WriteLine(#34;Major: {student.Major}");
// 解构赋值
string name;
int age;
string major;
(name, age, major) = student;
Console.WriteLine("------------------------------------");
Console.WriteLine(#34;Name: {name}");//$指在字符串中嵌入变量。
//name是一个变量,它的值将被插入到字符串中。
Console.WriteLine(#34;Age: {age}");
Console.WriteLine(#34;Major: {major}");
Console.WriteLine("------------------------------------");
Console.WriteLine("Name: "+student.Name);//看看和上面是输出是不是一样的
}
}
}
//尝试修改代码,观察结果变化
ValueTuple 还允许对不打算使用的成员进行“丢弃”解构。
// 对未使用的成员LName使用 下划线 _ 丢弃
(var id, var Name, _) = GetPerson();
注意,从 C# 12 开始,可以使用 using 指令指定元组类型的别名。 以下示例为元组类型添加 global using 别名,其中包含表示允许的 Min 值和 Max 值的两个整数值:
global using BandPass = (int Min, int Max);
声明别名后,可以将 BandPass 名称用作该元组类型的别名:
BandPass bracket = (40, 100);
Console.WriteLine(#34;The bandpass filter is {bracket.Min} to {bracket.Max}");
元组相等
元组类型支持 == 和 != 运算符。 这些运算符按照元组元素的顺序将左侧操作数的成员与相应的右侧操作数的成员进行比较。
完整示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ValueTupleType4
{
internal class Program
{
static void Main(string[] args)
{
(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right); // True
Console.WriteLine(left != right); //False
var t1 = (A: 5, B: 10);
var t2 = (B: 5, A: 10);
Console.WriteLine(t1 == t2); // True
Console.WriteLine(t1 != t2); // False
}
}
}