C#Tuples(元组)


本文摘自PHP中文网,作者PHPzhong,侵删。

1. 老版本代码


1

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

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

2. ValueTuple

不废话,直接看代码:


1

1 class Program 2 { 3     static void Main(string[] args) 4     { 5         var fullName = GetFullName(); 6  7         Console.WriteLine(fullName.First);  // 终于可以不是Item1,2,3了,,, 8         Console.WriteLine(fullName.Middle); 9         Console.WriteLine(fullName.Last);10     }11 12     static (string First, string Middle, string Last) GetFullName() => ("first name", "blackheart", "last name");13 }

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


1

1 internal class Program 2 { 3     private static void Main(string[] args) 4     { 5         ValueTuple<string, string, string> fullName = Program.GetFullName(); 6         Console.WriteLine(fullName.Item1); // 原来你还是Item1,2,3,,,FUCK!!! 7         Console.WriteLine(fullName.Item2); 8         Console.WriteLine(fullName.Item3); 9     }10 11     [TupleElementNames(new string[]12     {13             "First",14             "Middle",15             "Last"16     })]17     private static ValueTuple<string, string, string> GetFullName()18     {19         return new ValueTuple<string, string, string>("first name", "blackheart", "last name");20     }21 }

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

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

3. Example


1

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

look一下编译后的代码:


1

2

3

4

5

1 private static void Main(string[] args) 2 { 3     ValueTuple<int, int> range = new ValueTuple<int, int>(1, 10); 4     Console.WriteLine(range.Item1); 5     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;11     Console.WriteLine(begin);12     Console.WriteLine(end);13     ValueTuple<DateTime, DateTime> timeSpan = new ValueTuple<DateTime, DateTime>(DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31"));14     Console.WriteLine(timeSpan.Item1);15     Console.WriteLine(timeSpan.Item2);16 }

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

4. 总结

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

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

以上就是C#Tuples(元组)的详细内容!

相关阅读 >>

C#中关于new的用法以及和override的区别分析详解

C#获取本机ip搜集整理7种方法的示例代码分享

C#使用selenium+phantomjs抓取数据详解

C# 创建mdi窗体(图文)

详细介绍C# 利用irawpixels接口遍历栅格数据的代码实例

C#向word文档插入和隐藏段落的方法介绍

C#获取鼠标在listview右键点击单元格的内容方法详解

C#和.net是一个东西吗?C#与.net的区别与联系

利用unity脚本自定义分辨率实现相机截一张高清截图

C#与vb.net混合开发测试的详细介绍(图文)

更多相关阅读请进入《C#》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...

    正在狠努力加载,请稍候...