C# 7.0已经出来一段时间了,你们都知道新特性里面有个对元组的优化:ValueTuple。这里利用详尽的例子详解Tuple VS ValueTuple(元组类VS值元组).数据结构
Tuple是C# 4.0时出的新特性,.Net Framework 4.0以上版本可用。函数
元组是一种数据结构,具备特定数量和元素序列。好比设计一个三元组数据结构用于存储学生信息,一共包含三个元素,第一个是名字,第二个是年龄,第三个是身高。优化
元组的具体使用以下:ui
默认状况.Net Framework元组仅支持1到7个元组元素,若是有8个元素或者更多,须要使用Tuple的嵌套和Rest属性去实现。另外Tuple类提供创造元组对象的静态方法。设计
var testTuple6 = new Tuple<int, int, int, int, int, int>(1, 2, 3, 4, 5, 6); Console.WriteLine($"Item 1: {testTuple6.Item1}, Item 6: {testTuple6.Item6}"); var testTuple10 = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>>(1, 2, 3, 4, 5, 6, 7, new Tuple<int, int, int>(8, 9, 10)); Console.WriteLine($"Item 1: {testTuple10.Item1}, Item 10: {testTuple10.Rest.Item3}");
var testTuple6 = Tuple.Create<int, int, int, int, int, int>(1, 2, 3, 4, 5, 6); Console.WriteLine($"Item 1: {testTuple6.Item1}, Item 6: {testTuple6.Item6}"); var testTuple8 = Tuple.Create<int, int, int, int, int, int, int, int>(1, 2, 3, 4, 5, 6, 7, 8); Console.WriteLine($"Item 1: {testTuple8.Item1}, Item 8: {testTuple8.Rest.Item1}");
Note:这里构建出来的Tuple类型实际上是Tuple<int, int, int, int, int, int, int, Tuple<int>>,所以testTuple8.Rest取到的数据类型是Tuple<int>,所以要想获取准确值须要取Item1属性。调试
以下建立一个元组表示一个学生的三个信息:名字、年龄和身高,而不用单独额外建立一个类。code
var studentInfo = Tuple.Create<string, int, uint>("Bob", 28, 175); Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]");
当一个函数须要返回多个值的时候,通常状况下可使用out参数,这里能够用元组代替out实现返回多个值。orm
static Tuple<string, int, uint> GetStudentInfo(string name) { return new Tuple<string, int, uint>("Bob", 28, 175); }
static void RunTest() { var studentInfo = GetStudentInfo("Bob"); Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]"); }
4. 用于单参数方法的多值传递对象
当函数参数仅是一个Object类型时,可使用元组实现传递多个参数值。blog
static void WriteStudentInfo(Object student) { var studentInfo = student as Tuple<string, int, uint>; Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]"); }
static void RunTest() { var t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(WriteStudentInfo)); t.Start(new Tuple<string, int, uint>("Bob", 28, 175)); while (t.IsAlive) { System.Threading.Thread.Sleep(50); } }
尽管元组有上述方便使用的方法,可是它也有明显的不足:
所以在C# 7.0中引入了一个新的ValueTuple类型,详见下面章节。
ValueTuple是C# 7.0的新特性之一,.Net Framework 4.7以上版本可用。
值元组也是一种数据结构,用于表示特定数量和元素序列,可是是和元组类不同的,主要区别以下:
值元组的具体使用以下:
和元组类同样,.Net Framework值元组也只支持1到7个元组元素,若是有8个元素或者更多,须要使用值元组的嵌套和Rest属性去实现。另外ValueTuple类能够提供创造值元组对象的静态方法。
var testTuple6 = new ValueTuple<int, int, int, int, int, int>(1, 2, 3, 4, 5, 6); Console.WriteLine($"Item 1: {testTuple6.Item1}, Item 6: {testTuple6.Item6}"); var testTuple10 = new ValueTuple<int, int, int, int, int, int, int, ValueTuple<int, int, int>>(1, 2, 3, 4, 5, 6, 7, new ValueTuple <int, int, int>(8, 9, 10)); Console.WriteLine($"Item 1: {testTuple10.Item1}, Item 10: {testTuple10.Rest.Item3}");
var testTuple6 = ValueTuple.Create<int, int, int, int, int, int>(1, 2, 3, 4, 5, 6); Console.WriteLine($"Item 1: {testTuple6.Item1}, Item 6: {testTuple6.Item6}"); var testTuple8 = ValueTuple.Create<int, int, int, int, int, int, int, int>(1, 2, 3, 4, 5, 6, 7, 8); Console.WriteLine($"Item 1: {testTuple8.Item1}, Item 8: {testTuple8.Rest.Item1}");
注意这里构建出来的Tuple类型实际上是Tuple<int, int, int, int, int, int, int, Tuple<int>>,所以testTuple8.Rest取到的数据类型是Tuple<int>,所以要想获取准确值须要取Item1属性。
优化区别:当构造出超过7个元素以上的值元组后,可使用接下来的ItemX进行访问嵌套元组中的值,对于上面的例子,要访问第十个元素,既能够经过testTuple10.Rest.Item3访问,也能够经过testTuple10.Item10来访问。
var testTuple10 = new ValueTuple<int, int, int, int, int, int, int, ValueTuple<int, int, int>>(1, 2, 3, 4, 5, 6, 7, new ValueTuple<int, int, int>(8, 9, 10)); Console.WriteLine($"Item 10: {testTuple10.Rest.Item3}, Item 10: {testTuple10.Item10}");
以下建立一个值元组表示一个学生的三个信息:名字、年龄和身高,而不用单独额外建立一个类。
var studentInfo = ValueTuple.Create<string, int, uint>("Bob", 28, 175); Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]");
值元组也能够在函数定义中代替out参数返回多个值。
static ValueTuple<string, int, uint> GetStudentInfo(string name) { return new ValueTuple <string, int, uint>("Bob", 28, 175); }
static void RunTest() { var studentInfo = GetStudentInfo("Bob"); Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]"); }
优化区别:返回值能够不明显指定ValueTuple,使用新语法(,,)代替,如(string, int, uint):
static (string, int, uint) GetStudentInfo1(string name) { return ("Bob", 28, 175); }
static void RunTest1() { var studentInfo = GetStudentInfo1("Bob"); Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]"); }
调试查看studentInfo的类型就是ValueType三元组。
优化区别:返回值能够指定元素名字,方便理解记忆赋值和访问:
static (string name, int age, uint height) GetStudentInfo1(string name) { return ("Bob", 28, 175); }
static void RunTest1() { var studentInfo = GetStudentInfo1("Bob"); Console.WriteLine($"Student Information: Name [{studentInfo.name}], Age [{studentInfo.age}], Height [{studentInfo.height}]"); }
方便记忆赋值:
方便访问:
当函数参数仅是一个Object类型时,可使用值元组实现传递多个值。
static void WriteStudentInfo(Object student) { var studentInfo = (ValueTuple<string, int, uint>)student; Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]"); }
static void RunTest() { var t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(WriteStudentInfo)); t.Start(new ValueTuple<string, int, uint>("Bob", 28, 175)); while (t.IsAlive) { System.Threading.Thread.Sleep(50); } }
能够经过var (x, y)或者(var x, var y)来解析值元组元素构造局部变量,同时可使用符号”_”来忽略不须要的元素。
static (string name, int age, uint height) GetStudentInfo1(string name) { return ("Bob", 28, 175); } static void RunTest1() { var (name, age, height) = GetStudentInfo1("Bob"); Console.WriteLine($"Student Information: Name [{name}], Age [{age}], Height [{height}]"); (var name1, var age1, var height1) = GetStudentInfo1("Bob"); Console.WriteLine($"Student Information: Name [{name1}], Age [{age1}], Height [{height1}]"); var (_, age2, _) = GetStudentInfo1("Bob"); Console.WriteLine($"Student Information: Age [{age2}]"); }
由上所述,ValueTuple使C#变得更简单易用。较Tuple相比主要好处以下: