[你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二
anytao.net | 《你必須知道的.NET》網(wǎng)站 | Anytao技術(shù)博客?
發(fā)布日期:2009.06.01 作者:Anytao
? 2009 Anytao.com ,Anytao原創(chuàng)作品,轉(zhuǎn)貼請注明作者和出處。
Tuple,是函數(shù)式編程的概念之一,早見于Elang、F#等動態(tài)語言。不過,我第一次聽說Tuple還早在2005年園子的Ninputer大牛提出在.NET 2.0實(shí)現(xiàn)Tuple的基本想法,我們可以通過以下地址仰慕當(dāng)時的歷史片段:
探討.NET 2.0中Tuple的實(shí)現(xiàn)方法
由此可見,Tuple不是.NET 4.0的創(chuàng)造發(fā)明,但卻是C#趨于函數(shù)式編程概念的必要補(bǔ)充。那么,我們首先來看看,什么是Tuple?
Tuple為何物?
什么是Tuple,在漢語上我們將其翻譯為元組。Tuple的概念源于數(shù)學(xué)概念,表示有序的數(shù)據(jù)集合。在.NET中Tuple被實(shí)現(xiàn)為泛型類型,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>實(shí)例,該實(shí)例實(shí)現(xiàn)三個數(shù)據(jù)成員:
對于Tuple的具體解析我們隨后分析,當(dāng)下僅了解一個大致。
我們可以有兩個方面的理解,在.NET中關(guān)于Tuple我們有如下的定義:
- 廣義上, Tuple就是一種數(shù)據(jù)結(jié)構(gòu),通常情況下,其成員的類型及數(shù)據(jù)是確定的。
- 狹義上,凡是實(shí)現(xiàn)了ITuple接口的類型,都是Tuple的實(shí)例。在.NET 4.0 BCL中,預(yù)定義了8個Tuple類型。例如最簡單的Tuple定義為:
其他所有的Tuple類型都實(shí)現(xiàn)了ITuple接口,該接口被定義為:
interface ITuple {int Size { get; }int GetHashCode(IEqualityComparer comparer);string ToString(StringBuilder sb); }在該接口中,定義了一個只讀屬性Size、兩個覆寫方法GetHashCode和ToString,實(shí)現(xiàn)該接口的Tuple八大金剛?cè)缦?#xff1a;
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)方法,均被實(shí)現(xiàn)為顯示接口方法,所以只能以接口實(shí)例訪問,不過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呢?這是個值得權(quán)衡的問題,上述MyRequest類型中通過3-Tuple對需要的Request信息進(jìn)行封裝,我們當(dāng)然也可創(chuàng)建一個新的struct來封裝,兩種方式均可勝任。然則,在實(shí)際的編程實(shí)踐中,很多時候我們需要一種靈活的創(chuàng)建一定數(shù)據(jù)結(jié)構(gòu)的類型,很多時候新的數(shù)據(jù)結(jié)構(gòu)充當(dāng)著“臨時”角色,通過大動干戈新類型完全沒有必要,而Tuple既是為此種體驗(yàn)而設(shè)計的。例如:
- Point {X, Y},可以表示坐標(biāo)位置的數(shù)據(jù)結(jié)構(gòu)。
- Date {Year, Month, Day},可以表示日期結(jié)構(gòu);Time {Hour, Minute, Second},可以表示時間結(jié)構(gòu);而DateTime {Date, Time}則可以實(shí)現(xiàn)靈活的日期時間結(jié)構(gòu)。
- Request {Name, URL, Result},可以表示Request的若干信息。
- 。。。,隨需而取。
Tuple inside
為了對Tuple一探究竟,我們使用Reflector工具打開神秘之門,就實(shí)現(xiàn)而言,Tuple類型略顯單薄,并沒有什么“神奇”的設(shè)計,以Tuple<T1, T2>而言,我們可以看到其部分實(shí)現(xiàn):
[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而言,因?yàn)槠湓財?shù)量的有限性,雖然能夠滿足大部分的需求,當(dāng)時動態(tài)體驗(yàn)是我們越來越期望的編程體驗(yàn)。同時,尤其注意public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> 引發(fā)的可能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);將引發(fā)異常:
Unhandled Exception: System.ArgumentException: The last element of an eight element tuple must be a Tuple.
提示我們最后的TRest應(yīng)該為Tuple,所以修改程序?yàn)?#xff1a;
// 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>構(gòu)造方法中找到答案:
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類型參數(shù)必須被實(shí)現(xiàn)為ITuple,否則引發(fā)異常。TRest在某種程度上為元素的擴(kuò)展帶來點(diǎn)方便,但是我仔細(xì)想來,總覺此處TRest的設(shè)計有點(diǎn)多此一舉,既然是類型參數(shù),T1、T2、…、TN其實(shí)均可為ITuple實(shí)例,何必非拘泥于最后一個。
優(yōu)略之間
當(dāng)前,.NET 4.0預(yù)定義的Tuple類型僅有8個,所以我們應(yīng)考慮對于Tuple提供適度擴(kuò)展的可能, 然而遺憾的是ITuple類型被實(shí)現(xiàn)為internal,所以我們無法繼承ITuple,只好自定義類似的實(shí)現(xiàn):
優(yōu)勢所在:
- 為方法實(shí)現(xiàn)多個返回值體驗(yàn),這是顯然的,Tuple元素都可以作為返回值。
- 靈活的構(gòu)建數(shù)據(jù)結(jié)構(gòu),符合隨要隨到的公仆精神。
- 強(qiáng)類型。
不足總結(jié):
- 當(dāng)前Tuple類型的成員被實(shí)現(xiàn)為確定值,目前而言,還沒有動態(tài)決議成員數(shù)量的機(jī)制,如果你有可以告訴我:-)
- public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>,可能引發(fā)ArgumentException。
?
參考文獻(xiàn)
- 探討.NET 2.0中Tuple的實(shí)現(xiàn)方法
- Tuple, a new type on .Net 4.0
- Functional .NET 4.0 - Tuples and Zip
?
更多精彩,盡在anytao.net?
anytao | ? 2009 Anytao.com
2009/06/01 | http://anytao.cnblogs.com/ | http://anytao.net/blog/post/2009/05/31/anytao-insidenet-32-tupletalk.aspx
本文以“現(xiàn)狀”提供且沒有任何擔(dān)保,同時也沒有授予任何權(quán)利。 | This posting is provided "AS IS" with no warranties, and confers no rights.
本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
?
?
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的[你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 收藏:asp.net
- 下一篇: 学习asp.net ajax 笔记(一)