1. 老版本代码

 class Program
{
static void Main(string[] args)
{
var fullName = GetFullName(); Console.WriteLine(fullName.Item1);// Item1,2,3不能忍,,,
Console.WriteLine(fullName.Item2);
Console.WriteLine(fullName.Item3);
}
static Tuple<string, string, string> GetFullName() => new Tuple<string, string, string>("first name", "blackheart", "last name");
}

在有些场景下,我们需要一个方法返回一个以上的返回值,微软在.NET 4中引入了Tuple这个泛型类,可以允许我们返回多个参数,每个参数按照顺序被命名为 Item1;Item2,Item3 ,算是部分的解决了我们的问题,但是对于强迫症程序员来说,Item1,2,3的命名简直是不能忍的,,,so,在C#7中,引入了一个新的泛型类型ValueTuple<T>来解决这个问题,这个类型位于一个单独的dll(System.ValueTuple)中,可以通过nuget来引入到你当前的项目中(https://www.nuget.org/packages/System.ValueTuple/)。

2. ValueTuple

不废话,直接看代码:

 class Program
{
static void Main(string[] args)
{
var fullName = GetFullName(); Console.WriteLine(fullName.First); // 终于可以不是Item1,2,3了,,,
Console.WriteLine(fullName.Middle);
Console.WriteLine(fullName.Last);
} static (string First, string Middle, string Last) GetFullName() => ("first name", "blackheart", "last name");
}

看出来差别了吗?我们终于可以用更直观的名字来替换掉该死的"Item1,2,3"了,看起来很棒吧。但是貌似我们并没有用到上面我提到的System.ValueTuple,我们翻开编译后的程序集看看:

 internal class Program
{
private static void Main(string[] args)
{
ValueTuple<string, string, string> fullName = Program.GetFullName();
Console.WriteLine(fullName.Item1); // 原来你还是Item1,2,3,,,FUCK!!!
Console.WriteLine(fullName.Item2);
Console.WriteLine(fullName.Item3);
} [TupleElementNames(new string[]
{
"First",
"Middle",
"Last"
})]
private static ValueTuple<string, string, string> GetFullName()
{
return new ValueTuple<string, string, string>("first name", "blackheart", "last name");
}
}

不看不知道,一看吓一跳,原来我们的 fullName.First; 编译后居然还是 fullName.Item1 ,真是日了狗了。。。

不同之处在于GetFullName这个方法,编译器把我们简化的语法形式翻译成了 ValueTuple<string, string, string> ,还给加了一个新的Attribute(TupleElementNamesAttribute),然后把我们自定义的非常直观友好的“First”,"Middle","Last"当作元数据给存起来了(如果只是局部使用,则不会添加这样的元数据)。TupleElementNamesAttribute和ValueTuple一样,位于System.ValueTuple的单独dll中。

3. Example

 class Program
{
static void Main(string[] args)
{
var range = (first: , end: );
//也可以这样写,效果是一样的,编译后都是没有了first,end的痕迹,,,first和end只是语法层面的障眼法
//(int first, int last) range = (1, 10);
Console.WriteLine(range.first);
Console.WriteLine(range.end); //可以使用var,这种无显示声明一个变量的方式会编译出多余的代码,慎用,不知是不是还未优化好。
(var begin, var end) = (DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31"));
Console.WriteLine(begin);
Console.WriteLine(end); //begin,end可以被覆盖重命名为startDate和endDate,但是会有一个编译警告,提示名字被忽略掉了。
//warning CS8123: The tuple element name 'begin' is ignored because a different name is specified by the target type '(DateTime startDate, DateTime endDate)'
//warning CS8123: The tuple element name 'end' is ignored because a different name is specified by the target type '(DateTime startDate, DateTime endDate)‘
(DateTime startDate, DateTime endDate) timeSpan = (begin: DateTime.Parse("2017-1-1"), end: DateTime.Parse("2017-12-31"));
Console.WriteLine(timeSpan.startDate);
Console.WriteLine(timeSpan.endDate);
}
}

look一下编译后的代码:

 private static void Main(string[] args)
{
ValueTuple<int, int> range = new ValueTuple<int, int>(, );
Console.WriteLine(range.Item1);
Console.WriteLine(range.Item2);
6 ValueTuple<DateTime, DateTime> expr_3C = new ValueTuple<DateTime, DateTime>(DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31"));
7 DateTime item = expr_3C.Item1;
8 DateTime item2 = expr_3C.Item2;
9 DateTime begin = item;
10 DateTime end = item2;
Console.WriteLine(begin);
Console.WriteLine(end);
ValueTuple<DateTime, DateTime> timeSpan = new ValueTuple<DateTime, DateTime>(DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31"));
Console.WriteLine(timeSpan.Item1);
Console.WriteLine(timeSpan.Item2);
}

注意 (var begin, var end) = (DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31")); 这一行的便宜结果,看起来很是糟糕(上述6-10行红色部分),可能还是编译优化不足的问题吧(release编译也是如此)。

4. 总结

新的语法形式确实直观友好了好多,but,本质依然是借助泛型类型来实现的,同时也需要编译器对新语法形式的支持。

了解了本质是什么东西之后,以后在项目中环境允许的话,就放心大胆的使用吧(类型ValueTuple可以出现的地方,(first,last)这种新语法形式均可以)。

参考:

https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/

https://docs.microsoft.com/en-us/dotnet/articles/csharp/tuples

[C#7] 1.Tuples(元组)的更多相关文章

  1. 白话C#语法新特性之元组

    1.元组(Tuples) 元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的可读性,因为它的属性名都是:Item1,Item2.. . 2)Tuple 还不 ...

  2. [Python] 03 - Lists, Dictionaries, Tuples, Set

    Lists 列表 一.基础知识 定义 >>> sList = list("hello") >>> sList ['h', 'e', 'l', ' ...

  3. swift语言的学习笔记

    swift参考了OC,Rust,Haskell,Ruby,Python,C#等语言的特性.首先,学习这门语言是速学的,我不想浪费太多时间在笔记这门语言和其他语言的哪里不同,特性你自己亲自实践就知道了. ...

  4. Swift-1-基本概念

    // Playground - noun: a place where people can play // 通过代码快速了解swift常用知识,需要一定object-c基础 import UIKit ...

  5. swift:入门知识之控制流

    1.swift语句中的控制流和其他语言大致相同,使用if和switch作为条件控制.使用 for-in.for.while.do-while作为循环. 2.区别之处:小括号不是必须的,但是主体的大括号 ...

  6. Swift流程控制之循环语句和判断语句详解

    Swift提供了所有c类语言的控制流结构.包括for和while循环来执行一个任务多次:if和switch语句来执行确定的条件下不同的分支的代码:break和continue关键字能将运行流程转到你代 ...

  7. [干货来袭]C#7.0新特性(VS2017可用)

    前言 微软昨天发布了新的VS 2017 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下其实2016年12月就已经公布了的C#7 ...

  8. C#7.0新特性

    前言 微软昨天发布了新的VS 2017 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下其实2016年12月就已经公布了的C#7 ...

  9. C#版本和.NET版本以及VS版本的对应关系

    C#版本和.NET版本以及VS版本的对应关系 版本 .NET Framework版本 Visual Studio版本 发布日期 特性 C# 1.0 .NET Framework 1.0 Visual ...

  10. Scala详解

    1       快速入门... 4 1.1             分号... 4 1.2             常变量声明... 4 1.2.1         val常量... 4 1.2.2  ...

随机推荐

  1. PHP新手之学习数组声明

    数组是在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来的一种形式.这些按序排列的同类数据元素的集合称为数组.下面介绍PHP中的数组声明. 一.数组的概述 1.数组的本质:管理 ...

  2. 2.1. 托管对象模型是什么(Core Data 应用程序实践指南)

    托管对象模型是一种数据结构.在这里,数据结构.纲要.对象图.数据模型.托管对象模型这些术语是一个意思.它们是对同一个东西不同场景的描述.比如,对Core Data 而言是托管对象模型,对设计器来说是对 ...

  3. MongoDB安装环境搭建

    Mongodb的默认端口号27017 _id是全局唯一值,不要去给这个列赋值,默认是唯一的,如果赋值,列入有两列的_id:2,则会报冲突不能插入 [root@HE4 ~]# tar xvf mongo ...

  4. Objective-C处理动态类型函数集

    -(BOOL) isKindOfClass:class-object 对象是不是class-object或其子类的实例-(BOOL) isMemberOfClass:class-object 对象是不 ...

  5. Redis缓存数据之简单逻辑

    并发不高的情况: 读: 读redis->没有,读DataBase->把DB数据写回redis,有的话直接从redis中取: 写: 写DataBase->成功,再写redis: 并发高 ...

  6. There is no getter for property named 'userId' in 'class java.lang.String'

    [ERROR] 2017-01-18 04:37:06:231 cn.dataenergy.common.CenterHandlerExceptionResolver (CenterHandlerEx ...

  7. 游戏开发之在UE4中编写C++代码控制角色

    当你运行我们上次做完的项目,你可能会意识到我们移动的摄像机还是默认的那个摄像机,这个默认的摄像机可以自由飞翔.这一节,我们要使得开始的角色是我们的一个Avatar类的实例对象,并且使用键盘控制我们的角 ...

  8. System.Web.Caching.Cache 方法汇总

    在做后台的时候,想着把所有栏目放到缓存里,就这里了一个类.必然是有缺陷,暂时没有实现滑动缓存 using System; using System.Collections; using System. ...

  9. 私有云存储搭建(owncloud)

    第一步.搭建LAMP(基于linux7.1.1503) 1 配置yum(网络加本地,下面为网络) [vault.centos.org_7.1.1503_os_x86_64_] name=added f ...

  10. CSS_position

    1. HTML Code: <div id="example"> <div id="div-before"> <p>id = ...