C# 7.0已经出来一段时间了,大家都知道新特性里面有个对元组的优化:ValueTuple。这里利用详尽的例子详解Tuple VS ValueTuple(元组类VS值元组),10分钟让你更了解ValueTuple的好处和用法。

如果您对Tuple足够了解,可以直接跳过章节”回顾Tuple”,直达章节”ValueTuple详解”,查看值元组的炫丽用法。

回顾Tuple

Tuple是C# 4.0时出的新特性,.Net Framework 4.0以上版本可用。

元组是一种数据结构,具有特定数量和元素序列。比如设计一个三元组数据结构用于存储学生信息,一共包含三个元素,第一个是名字,第二个是年龄,第三个是身高。

元组的具体使用如下:

1.    如何创建元组

默认情况.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}");
  • 利用Tuple静态方法构建元组,最多支持八个元素:

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属性。

2.    表示一组数据

如下创建一个元组表示一个学生的三个信息:名字、年龄和身高,而不用单独额外创建一个类。

var studentInfo = Tuple.Create<string, int, uint>("Bob", 28, 175);
Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]");

3.    从方法返回多个值

当一个函数需要返回多个值的时候,一般情况下可以使用out参数,这里可以用元组代替out实现返回多个值。

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类型时,可以使用元组实现传递多个参数值。

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);}
}

尽管元组有上述方便使用的方法,但是它也有明显的不足:

  • 访问元素的时候只能通过ItemX去访问,使用前需要明确元素顺序,属性名字没有实际意义,不方便记忆;

  • 最多有八个元素,要想更多只能通过最后一个元素进行嵌套扩展;

  • Tuple是一个引用类型,不像其它的简单类型一样是值类型,它在堆上分配空间,在CPU密集操作时可能有太多的创建和分配工作。

因此在C# 7.0中引入了一个新的ValueTuple类型,详见下面章节。

ValueTuple详解

ValueTuple是C# 7.0的新特性之一,.Net Framework 4.7以上版本可用。

值元组也是一种数据结构,用于表示特定数量和元素序列,但是是和元组类不一样的,主要区别如下:

  • 值元组是结构,是值类型,不是类,而元组(Tuple)是类,引用类型;

  • 值元组元素是可变的,不是只读的,也就是说可以改变值元组中的元素值;

  • 值元组的数据成员是字段不是属性。

值元组的具体使用如下:

1.    如何创建值元组

和元组类一样,.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}");
  • 利用Tuple静态方法构建元组,最多支持八个元素:

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}");

2.    表示一组数据

如下创建一个值元组表示一个学生的三个信息:名字、年龄和身高,而不用单独额外创建一个类。

var studentInfo = ValueTuple.Create<string, int, uint>("Bob", 28, 175);
Console.WriteLine($"Student Information: Name [{studentInfo.Item1}], Age [{studentInfo.Item2}], Height [{studentInfo.Item3}]");

3.    从方法返回多个值

值元组也可以在函数定义中代替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}]");
}

方便记忆赋值:

方便访问:

4.    用于单参数方法的多值传递

当函数参数仅是一个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);}
}

5.    解构ValueTuple

可以通过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相比主要好处如下:

  • ValueTuple支持函数返回值新语法”(,,)”,使代码更简单;

  • 能够给元素命名,方便使用和记忆,这里需要注意虽然命名了,但是实际上value tuple没有定义这样名字的属性或者字段,真正的名字仍然是ItemX,所有的元素名字都只是设计和编译时用的,不是运行时用的(因此注意对该类型的序列化和反序列化操作);

  • 可以使用解构方法更方便地使用部分或全部元组的元素;

  • 值元组是值类型,使用起来比引用类型的元组效率高,并且值元组是有比较方法的,可以用于比较是否相等,详见:https://msdn.microsoft.com/en-us/library/system.valuetuple。

原文地址:http://www.cnblogs.com/lavender000/p/6916157.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

详解C# Tuple VS ValueTuple(元组类 VS 值元组)相关推荐

  1. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

  2. java ftp ftpclient_详解JAVA中使用FTPClient工具类上传下载

    详解JAVA中使用FTPClient工具类上传下载 在Java程序中,经常需要和FTP打交道,比如向FTP服务器上传文件.下载文件.本文简单介绍如何利用jakarta commons中的FTPClie ...

  3. c语言 long类型取值范围,详解 IOS下int long longlong的取值范围

    详解 IOS下int long longlong的取值范围 32bit下: unsigned int 0-4294967295 int -2147483648-2147483647 unsigned ...

  4. python中的super用法详解_【Python】【类】super用法详解

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1: 代码段1: class A: def __init__(sel ...

  5. 计算机学校专业工学,大学专业详解:工学(仪器仪表类)

    一 专业详解 080401 测控技术与仪器 培养目标:本专业培养机电结合,掌握机械工业自动化.电力电子和计算机应用等技术,从事机械装备运行管理,机电新产品设计.开发,计算机辅助设计.计算机辅助管理,以 ...

  6. java unsafe 详解_Java CAS操作与Unsafe类详解

    一.复习 计算机内存模型,synchronized和volatile关键字简介 二.两者对比 sychronized和volatile都解决了内存可见性问题 不同点: (1)前者是独占锁,并且存在者上 ...

  7. 《Android游戏开发详解》一2.9 类

    本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.9节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区 ...

  8. MQTT协议详解及v5.0实践——实践类

    本文主要包含了以下内容: 1)MQTT协议演进历史及协议特点,总结和分析MQTT协议族的优缺点,分析和总结了为什么相比于其他协议,MQTT适合IoT,业内支持现状等. 2)阿里云IoT MQTT3和5 ...

  9. 词云生成库wordcloud详解(三):IntegralOccupancyMap类——词云布局机制

    当前wordcloud版本:1.81 词云绘制需求 在绘制词云时大概有以下需求: 词与词之间相互不重叠. 尽可能填充满整个空间,词与词之间间隙比较小. 空间可能按照某张图片布局,即所有词要布局在图片的 ...

最新文章

  1. MIS开发中.net Framework的打印功能
  2. 160个Crackme004
  3. 逻辑性最强的React Native环境搭建与调试
  4. 用Eclipse 统计代码行数小技巧
  5. flash as3鼠标左右拖动元件
  6. 讨论简书留言界面的设计
  7. flacs 安装教程_文章详细信息
  8. 蓝桥杯网站试题练习系统网站,想拿国奖就靠它
  9. 线性同余法产生1000个随机数
  10. 聚类分析软件测试,基于复杂网络的软件测试路径聚类分析-计算机工程与应用.PDF...
  11. 电脑知识:台式电脑如何使用无线网上网?
  12. 基于微信小程序的毕业设计题目(26)php视频电影播放小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板)
  13. python3下使用有道翻译网页版实现翻译功能~~~附源码
  14. 电商中,订单号的生成方法
  15. GitHub Actions入门教程:自动化部署静态博客
  16. php 微信表情存储,轻松处理PHP开发中微信emoji表情mysql存储的问题
  17. 游戏开发论坛_国内游戏开发站点与论坛
  18. 微信九宫图生成HTML源码
  19. 重构业务系统,我是这样做的
  20. 队列等待之enq: TX - row lock contention

热门文章

  1. Centos 手工创建新用户
  2. Windows Server 2008关闭默认windows共享
  3. 送给“苦逼”的IT人系列1:IT人的“钱”景以及收入的两道坎
  4. 钱德沛教授:云计算和网格计算差别何在?
  5. 如何获取 Process.Start 打开进程的输出结果?
  6. 迎.NET6,今日先送200P全新视频教程 / 源码
  7. C# WPF文本框TextEdit不以科学计数法显示
  8. SqlBulkCopy只支持SQL Server? EF Core实现支持多数据库类型的Bulk Copy
  9. .net5或.net6(Preview) 之 顶级语句
  10. Docker查看应用的实际内存