本文告诉大家一些 ValueTuple 的原理,避免在使用出现和期望不相同的值。ValueTuple 是 C# 7 的语法糖,如果使用的 .net Framework 是 4.7 以前,那么需要使用 Nuget 安装System.ValueTuple

虽然 ValueTuple 的很好用,但是需要知道他有两个地方都是在用的时候需要知道他原理。如果不知道原理,可能就发现代码和预期不相同

json 转换

先创建一个项目,然后安装 Json 解析,使用下面的代码,在运行之前,先猜一下,下面的代码会出现什么

            var foo = (name: "lindexi", site: "blog.csdn.net/lindexi_gd");
var str = JsonConvert.SerializeObject(foo);

实际上输出的是 {"Item1":"lindexi","Item2":"blog.csdn.net/lindexi_gd"}

那么刚才的命名在哪?

如果想知道,那么请看 ValueTuple 的原理

原理

先来写一段代码,编译之后对他反编译,看一下他是怎么做的

        static void Main(string[] args)
{
var foo = Foo();
var str = JsonConvert.SerializeObject(foo);
Console.WriteLine(str);
} static (string name, string site) Foo()
{
return (name: "lindexi", site: "blog.csdn.net/lindexi_gd");
}

不需要安装反编译软件,可以使用这个网站拿到反编译

可以看到Foo被编译为 TupleElementNames 特性的两个字符串

    [return: TupleElementNames(new string[]
{
"name",
"site"
})]
private static ValueTuple<string, string> Foo()
{
return new ValueTuple<string, string>("lindexi", "blog.csdn.net/lindexi_gd");
}

所以实际上代码是 ValueTuple<string, string> 不是刚才定义的代码,只是通过 TupleElementNames 让编译器知道值,所以是语法糖。

IL 代码是

private hidebysig static valuetype [mscorlib]System.ValueTuple`2<string, string>
Foo() cil managed
{
.param [0]
.custom instance void [mscorlib]System.Runtime.CompilerServices.TupleElementNamesAttribute::.ctor(string[])
= (
01 00 02 00 00 00 04 6e 61 6d 65 04 73 69 74 65 // .......name.site 这里就是 return: TupleElementNames 的命名
00 00 // ..
)
.maxstack 2
.locals init (
[0] valuetype [mscorlib]System.ValueTuple`2<string, string> V_0
) // [20 9 - 20 10]
IL_0000: nop // [21 13 - 21 72]
IL_0001: ldstr "lindexi"
IL_0006: ldstr "blog.csdn.net/lindexi_gd"
IL_000b: newobj instance void valuetype [mscorlib]System.ValueTuple`2<string, string>::.ctor(!0/*string*/, !1/*string*/)
IL_0010: stloc.0 // V_0
IL_0011: br.s IL_0013 // [22 9 - 22 10]
IL_0013: ldloc.0 // V_0
IL_0014: ret }

这个特性只有编译器可以用,不可以在代码使用。

在上面的解释,实际上 IL 不知道存在定义的命名,所以不可以通过这个方法获得值。

动态类型获得值

如果希望使用动态类型获得值,那么下面的代码实际上会运行出现异常

        static void Main(string[] args)
{
dynamic foo = Foo();
Console.WriteLine(foo.name);
} static (string name, string site) Foo()
{
return (name: "lindexi", site: "blog.csdn.net/lindexi_gd");
}

运行出现 RuntimeBinderException 异常,因为没有发现 name 属性

实际上对比下面匿名类,也就是很差不多写法。

        dynamic foo = new { name = "lindexi", site = "blog.csdn.net/lindexi_gd" };
Console.WriteLine(foo.name);

运行是可以的,所以在使用动态类型,请不要使用 ValueTuple ,如果需要使用,那么请知道有存在找不到变量异常,而且是在运行才出现异常。

其他需要知道的

不要随便定义一个看不懂的值

实际上下面的代码,编译是可以通过

(int x, (int y, (float a, float b))[] c) f1

但是这个值,在看的时候,几乎说不出他的属性

第二个需要知道的,ValueTuple 是值类型,所以他的默认值不是 null 而是 default(xx),在C# 7.2 支持使用关键字,所以不需要去写 defalut(xx,xx)

关于 ValueTuple 变量名的定义也是很难说的,有的小伙伴觉得需要使用 Axx 的方式命名,但是很多小伙伴觉得使用 aaBa 的命名更好,所以暂时对于他的命名,大家觉得什么方式好请告诉我

参见:Exploring Tuples as a Library Author

C# 7: Dynamic types and Reflection cannot access Tuple fields by name

我搭建了自己的博客 https://lindexi.gitee.io/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

C# ValueTuple 原理的更多相关文章

  1. dotnet 从入门到放弃的 500 篇文章合集

    本文是记录我从入门到放弃写的博客 博客包括 C#.WPF.UWP.dotnet core .git 和 VisualStudio 和一些算法,所有博客使用 docx 保存 下载:dotnet 从入门到 ...

  2. 2018-8-10-C#-ValueTuple-原理

    title author date CreateTime categories C# ValueTuple 原理 lindexi 2018-08-10 19:16:52 +0800 2018-2-13 ...

  3. 2018-8-10-dotnet-从入门到放弃的-500-篇文章合集

    title author date CreateTime categories dotnet 从入门到放弃的 500 篇文章合集 lindexi 2018-08-10 19:16:52 +0800 2 ...

  4. 使用newtonsoft完美序列化WebApi返回的ValueTuple

    由于开发功能的需要,又懒得新建太多的class,所以ValueTuple是个比较好的偷懒方法,但是,由于WebApi需要返回序列化后的json,默认的序列化只能将ValueTuple定义的各个属性序列 ...

  5. 奇异值分解(SVD)原理与在降维中的应用

    奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...

  6. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  7. 线性判别分析LDA原理总结

    在主成分分析(PCA)原理总结中,我们对降维算法PCA做了总结.这里我们就对另外一种经典的降维方法线性判别分析(Linear Discriminant Analysis, 以下简称LDA)做一个总结. ...

  8. [原] KVM 虚拟化原理探究(1)— overview

    KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...

  9. H5单页面手势滑屏切换原理

    H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...

随机推荐

  1. LOJ-10108(欧拉回路+并查集)一个图至少用几笔画成

    题目链接:传送门 思路: 用并查集统计出每个区块奇数个节点的个数x,每个区块对笔画的贡献是max(x/2,1): 然后每个区块求和即可. #include<iostream> #inclu ...

  2. Java并发编程73道面试题及答案

    原文出处:https://blog.csdn.net/qq_34039315/article/details/7854931 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线 ...

  3. MySQL-5.7安装

    2.1 下载mysql 网址:https://www.mysql.com/ [root@localhost ~]# mkdir -p /root/soft/MySQL [root@localhost ...

  4. C程序编程规范一

    和身边一些学弟们接触发现他们的编程习惯不是太好,对一些基本的规范不重视,今天有时间写一些基本的规范给一些刚入门的新手们,高手可忽略. 首先做项目来说需要建立工程,一般需要几个到几百个上上千个C文件,这 ...

  5. Vuejs——(1)入门(单向绑定、双向绑定、列表渲染、响应函数)

    版权声明:出处http://blog.csdn.net/qq20004604   目录(?)[+]   参照链接: http://cn.vuejs.org/guide/index.html [起步]部 ...

  6. HTTPS抓包之Charles

    这里对HTTP请求的抓包操作不做讲解了,只讲解HTTPS的抓包要进行的操作. [说明]:下面以MAC电脑示例,Windows版本可参考:http://weibo.com/ttarticle/p/sho ...

  7. 【接口时序】3、UART串口收发的原理与Verilog实现

    一.软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE14.7 3.仿真工具:ModelSim-10.4-SE 硬件平台: 1.FPGA型号:XC6SLX45- ...

  8. 深入浅出TCP/IP协议

    目录 什么是网络协议? 谁来制定这个网络协议? TCI/IP协议 什么是socket? http协议属于应用层还是传输层? soap可以使用HTTP协议进行传输吗? 各层协议举例 什么是网络协议? 话 ...

  9. 前端学习之路-CSS介绍,Html介绍,JavaScript介绍

    CSS介绍 学前端必备掌握CSS样式,css为层叠样式表,用来定义页面的显示效果,加强用户的体验乐趣,那么如何用css到html中呢? style属性方式 利用标签中的style属性来改变显示样式 & ...

  10. ubuntu root默认密码(初始密码)

    ubuntu安装好后,root初始密码(默认密码)不知道,需要设置. 1.先用安装时候的用户登录进入系统 2.输入:sudo passwd  按回车 3.输入新密码,重复输入密码,最后提示passwd ...