[你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二

Tuple,是函数式编程的概念之一,早见于Elang、F#等动态语言。不过,我第一次听说Tuple还早在2005年园子的Ninputer大牛提出在.NET 2.0实现Tuple的基本想法,我们可以通过以下地址仰慕当时的历史片段: 
探讨.NET 2.0中Tuple的实现方法 
由此可见,Tuple不是.NET 4.0的创造发明,但却是C#趋于函数式编程概念的必要补充。那么,我们首先来看看,什么是Tuple?

Tuple为何物?

什么是Tuple,在汉语上我们将其翻译为元组。Tuple的概念源于数学概念,表示有序的数据集合。在.NET中Tuple被实现为泛型类型,n-Tuple表示有n个元素的Tuple,集合的元素可以是任何类型,例如定义一个3-Tuple表示Date(Year, Month, Day)时可以定义为:

// Release : code01, 2009/05/29
// Author  : Anytao, http://www.anytao.com
var date = Tuple.Create<int, int, int>(2009, 5, 29);

通过Tuple.Create<int, int, int>将定义一个Tuple<int, int, int>实例,该实例实现三个数据成员:

o_anytao-insidenet-32-01[1]

对于Tuple的具体解析我们随后分析,当下仅了解一个大致。

我们可以有两个方面的理解,在.NET中关于Tuple我们有如下的定义:

  • 广义上, Tuple就是一种数据结构,通常情况下,其成员的类型及数据是确定的。
  • 狭义上,凡是实现了ITuple接口的类型,都是Tuple的实例。在.NET 4.0 BCL中,预定义了8个Tuple类型。例如最简单的Tuple定义为:
public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
{
}

其他所有的Tuple类型都实现了ITuple接口,该接口被定义为:

interface ITuple
{int Size { get; }int GetHashCode(IEqualityComparer comparer);string ToString(StringBuilder sb);
}

在该接口中,定义了一个只读属性Size、两个覆写方法GetHashCode和ToString,实现该接口的Tuple八大金刚如下:

public class Tuple<T1>
public class Tuple<T1, T2>
public class Tuple<T1, T2, T3>
public class Tuple<T1, T2, T3, T4>
public class Tuple<T1, T2, T3, T4, T5>
public class Tuple<T1, T2, T3, T4, T5, T6>
public class Tuple<T1, T2, T3, T4, T5, T6, T7>
public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>

注:Size属性、ToString(StringBuilder sb)方法,均被实现为显示接口方法,所以只能以接口实例访问,不过ITuple本身被定义internal,意味着我们无法在程序中访问ITuple,何意何解尚不明确。

在下面的定义中,我们将Custom Request封装为Tuple:

// Release : code02, 2009/05/29
// Author  : Anytao, http://www.anytao.com
public class MyRequest
{public Tuple<string, Uri, DateTime> GetMyRequest(){return Tuple.Create<string, Uri, DateTime>("anytao.com", new Uri("http://anytao.net/"), DateTime.Now);}
}

为什么要用Tuple呢?这是个值得权衡的问题,上述MyRequest类型中通过3-Tuple对需要的Request信息进行封装,我们当然也可创建一个新的struct来封装,两种方式均可胜任。然则,在实际的编程实践中,很多时候我们需要一种灵活的创建一定数据结构的类型,很多时候新的数据结构充当着“临时”角色,通过大动干戈新类型完全没有必要,而Tuple既是为此种体验而设计的。例如:

  • Point {X, Y},可以表示坐标位置的数据结构。
  • Date {Year, Month, Day},可以表示日期结构;Time {Hour, Minute, Second},可以表示时间结构;而DateTime {Date, Time}则可以实现灵活的日期时间结构。
  • Request {Name, URL, Result},可以表示Request的若干信息。
  • 。。。,随需而取。

Tuple inside

为了对Tuple一探究竟,我们使用Reflector工具打开神秘之门,就实现而言,Tuple类型略显单薄,并没有什么“神奇”的设计,以Tuple<T1, T2>而言,我们可以看到其部分实现:

[Serializable]
public class Tuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
{// Fieldsprivate T1 m_Item1;private T2 m_Item2;// Methodspublic Tuple(T1 item1, T2 item2){this.m_Item1 = item1;this.m_Item2 = item2;}string ITuple.ToString(StringBuilder sb){sb.Append(this.m_Item1);sb.Append(", ");sb.Append(this.m_Item2);sb.Append(")");return sb.ToString();}int ITuple.Size{get{return 2;}}// Propertiespublic T1 Item1{get{return this.m_Item1;}}public T2 Item2{get{return this.m_Item2;}}//More and more...
}

其他的Tuple类型也大致如此,所以我们易于知晓Item1、Item2、…、ItemN是如何被定义的,同时也纳闷Size属性将何去何从,也打消了我们期望通过foreach来遍历Tuple元素的可能,未来如何,只有期待。

不过,对于Tuple而言,因为其元素数量的有限性,虽然能够满足大部分的需求,当时动态体验是我们越来越期望的编程体验。同时,尤其注意public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> 引发的可能ArgumentException,例如:

// Release : code03, 2009/05/31
// Author  : Anytao, http://www.anytao.com
var t8 = Tuple.Create<int, int, int, int, int, int, int, int>(1, 2, 3, 4, 5, 6, 7, 8);
Console.WriteLine(t8.Rest);

将引发异常:

Unhandled Exception: System.ArgumentException: The last element of an eight element tuple must be a Tuple.

提示我们最后的TRest应该为Tuple,所以修改程序为:

// Release : code04, 2009/05/31
// Author  : Anytao, http://www.anytao.com
var trest = Tuple.Create<int>(8);
var t8 = Tuple.Create<int, int, int, int, int, int, int, Tuple<int>>(1, 2, 3, 4, 5, 6, 7, trest);
Console.WriteLine(t8.Rest);

则没有任何问题,究其原因我们很容易从Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>构造方法中找到答案:

public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest)
{if (!(rest is ITuple)){throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleLastArgumentNotATuple"));}this.m_Item1 = item1;this.m_Item2 = item2;this.m_Item3 = item3;this.m_Item4 = item4;this.m_Item5 = item5;this.m_Item6 = item6;this.m_Item7 = item7;this.m_Rest = rest;
}

TRest类型参数必须被实现为ITuple,否则引发异常。TRest在某种程度上为元素的扩展带来点方便,但是我仔细想来,总觉此处TRest的设计有点多此一举,既然是类型参数,T1、T2、…、TN其实均可为ITuple实例,何必非拘泥于最后一个。

优略之间

当前,.NET 4.0预定义的Tuple类型仅有8个,所以我们应考虑对于Tuple提供适度扩展的可能, 然而遗憾的是ITuple类型被实现为internal,所以我们无法继承ITuple,只好自定义类似的实现:

优势所在:

  • 为方法实现多个返回值体验,这是显然的,Tuple元素都可以作为返回值。
  • 灵活的构建数据结构,符合随要随到的公仆精神。
  • 强类型。

不足总结:

  • 当前Tuple类型的成员被实现为确定值,目前而言,还没有动态决议成员数量的机制,如果你有可以告诉我:-)
  • public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>,可能引发ArgumentException。

 

参考文献

  • 探讨.NET 2.0中Tuple的实现方法
  • Tuple, a new type on .Net 4.0
  • Functional .NET 4.0 - Tuples and Zip

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438686.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

支持商用吗_可商用的插画素材 | 美翻了

好素材在手&#xff0c;天下我有啊...哈哈哈喽大家周末好&#xff0c;那上周公子做的那份工作型插画模板呢&#xff0c;很多小伙伴都来问我素材是哪里找的&#xff0c;自己画的吗当然不是了&#xff01;其实我在文章中已经提到了&#xff0c;那有的人可能之前用过或可以自己找到…

永恒边境白羊座服务器维护,永恒边境升级攻略 速升50级技巧

永恒边境怎么升级快&#xff1f;分享永恒边境升级攻略&#xff0c;下面我们就一起来看看永恒边境速刷主线支线任务技巧&#xff0c;希望对大家有所帮助。20-30级篇在这个阶段&#xff0c;我们就主线任务和支线任务大家都不要错过了&#xff0c;都要好好抓住&#xff0c;我还可以…

格式化css文件,css文件格式化脚本的方法

这次给大家带来css文件格式化脚本的方法&#xff0c;css文件格式化脚本的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。#!/usr/bin/python# -*- coding: UTF-8 -*-import sys,osdef format(ddt):ddt ddt.replace(\n,)#去除换行ddtddt.replace(;},}).…

[你必须知道的.NET]第三十四回,object成员,不见了!

在.NET世界了&#xff0c;object是公认的造物主&#xff0c;其麾下的7大成员&#xff0c;个顶个的横行在任何系统的任何代码角落。 public class Object {public Object();public virtual bool Equals(object obj);public static bool Equals(object objA, object objB);publi…

直接请求接口_http类型的post和get接口测试

我们做接口测试时候&#xff0c;会发现通常需要测试的接口类型有好几种&#xff0c;比较多的是http类型的接口&#xff0c;其他还有webservice接口&#xff0c;rpc接口等等&#xff0c;本次主要说下http类型的接口我们该怎么测试&#xff0c;还有该测试哪些东西。HTTP接口概念:…

css3加载中动画效果,CSS3实现加载中的动画效果

Loading 的菊花图形组合的不太好&#xff0c;基本上实现这个功能了动画解析这个动画用到的 CSS3 特性:transform 主要使用 transform 属性的 rotate&#xff0c;将线条组合成 Loading 图形 (也就是常见的菊花图形)animation 实现将线条颜色由浅到深&#xff0c;再由深到浅来回变…

[你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题

问题的提出 晚上翻着群里的聊天&#xff0c;发现一个有趣的问题&#xff1a;如何通过编码方式来判断一个dll或者exe为debug build还是release build&#xff1f;由于没有太多的讨论&#xff0c;所以我只好自己找点儿办法&#xff0c;试图解决这个问题&#xff0c;为夜生活带点…

执行本地sql_实用!5个在线 SQL 数据库环境

文章目录SQL FiddleDB Fiddledb<>fiddleSQL OnlineOracle Live SQL总结大今天给大家分享几个在线的免费 SQL 运行环境&#xff0c;也就是在线数据库。这些网站可以帮助我们快速运行一些 SQL 语句的测试或者验证&#xff0c;同时还可以在网络上进行分享&#xff0c;关键不…

ocp证书怎么考_没有基础怎么考初级会计证书?

初级会计证书这些年来越发火热&#xff0c;报考门槛也较低。多数报考初级会计证的考生都是没有基础的&#xff0c;那么怎么复习呢?今天会计网将给大家带来没有基础怎么考初级会计证书?1、制定一份适合自己的学习计划&#xff0c;分阶段学习对于没有基础的考生而言&#xff0c…

与gps优缺点_长缨在手,敢缚苍龙,中国北斗三号圆满收官,相比美国GPS怎样?...

2020年6月23日&#xff0c;北斗三号最后一颗全球组网卫星发射成功&#xff0c;完美收官。我们都知道信息化时代定位导航的重要性&#xff0c;那么中国北斗和美国GPS相对比怎么样呢&#xff1f;首先来了解一下北斗。中国的北斗导航系统是分三步建设的。卫星导航系统第一步在1994…

11单件模式(Singleton Pattern)

创建型模式---单件模式(Singleton Pattern)动机&#xff08;Motivation): 在软件系统中&#xff0c;经常有这样一些特殊的类&#xff0c;必须保证它们在系统中只存在一个实例&#xff0c;才能确保它们的逻辑正确性、以及良好的效率。 如何绕过常规的构造器&#xff0c;…

查找字符位置_如何使用find函数和search函数精确查找字符

精确查找指定字符在一个字符串中的位置是Excel函数运用中的一项重要的技巧&#xff0c;尤其是在截取字符串、替换字符串等文本处理过程中&#xff0c;精确定位技术更是必不可少。查找字符的主要函数是find函数和search函数&#xff0c;两者的语法完全相同。find(find_text,with…

12抽象工厂(Abstract Factory)

常规的对象创建方法&#xff1a; //创建一个Road对象 Road road new Road(); new 的问题&#xff1a; 实现依赖&#xff0c;不能应对“具体实例化类型”的变化。解决思路&#xff1a; 封装变化点-----哪里变化&#xff0c;封装哪里 潜台词&#xff1a; 如果没有变…

13建造者模式(Builder)

Builder模式的缘起&#xff1a; 假设创建游戏中的一个房屋House设施&#xff0c;该房屋的构建由几部分组成&#xff0c;且各个部分富于变化。如果使用最直观的设计方法&#xff0c;每一个房屋部分的变化&#xff0c;都将导致房屋构建的重新修正.....动机&#xff08;Motiva…

15原型模式(Prototype)

依赖关系倒置&#xff1a; 动机(Motivate): 在软件系统中&#xff0c;经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化&#xff0c;这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。 如何应对这种变化&#xff1f;如何向“客户…

14工厂方法模式(Factory Method)

耦合关系&#xff1a; 动机(Motivation): 在软件系统中&#xff0c;由于需求的变化&#xff0c;"这个对象的具体实现"经常面临着剧烈的变化&#xff0c;但它却有比较稳定的接口。 如何应对这种变化呢&#xff1f;提供一种封装机制来隔离出"这个易…

mysql 更新错误1062_mysql 出现1062错误怎么办

mysql 出现1062错误的解决办法&#xff1a;首先打开mysql的配置文件【my.cnf】&#xff1b;然后在client和mysqld下面加上相关代码&#xff1b;最后存关闭后重启mysql即可。mysql 出现1062错误的解决办法&#xff1a;两个instance的版本接近&#xff0c;猜测不是版本问题。执行…

21适配器模式(Adapter Pattern)

适配&#xff08;转换&#xff09;的概念无处不在...... 适配&#xff0c;即在不改变原有实现的基础上&#xff0c;将原先不兼容的接口转换为兼容的接口。 例如&#xff1a;二转换为三箱插头&#xff0c;将高电压转换为低电压等。 动机(Motivate): 在软件系统中&#…

22桥接模式(Bridge Pattern)

动机(Motivate): 在软件系统中&#xff0c;某些类型由于自身的逻辑&#xff0c;它具有两个或多个维度的变化&#xff0c;那么如何应对这种“多维度的变化”&#xff1f;如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化&#xff0c;而又不引入额外的复杂度…

mysql动静分离_haproxy的web服务负载均衡、动静分离、 MySQL服务负载均衡、状态监控...

实验环境&#xff1a;基于centos6.6haproxy-Server&#xff1a;172.16.249.98 hostname:node1upsteram server1&#xff1a;172.16.249.100 hostname:node2upstream server2&#xff1a;172.16.249.99 hostname:node3web服务的负载均衡以及状态监控&#xff1a;设置记录hapro…