Tuple簡介

by vivid 4. 五月 2016 03:20

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N160517101

出刊日期:2016/5/4
開發工具:Visual Studio 2015 Enterprise Update 1
版本:.NET Framework 4.6、C# 6

.NET Framework 4版新增Tuple物件,Tuple是一個有序的資料結構,可以儲存異質物件。在這篇文章之中,將介紹Tuple物件的基本用法。

根據定義,Tuple類别總共有8個多載的Create方法,其定義表列如下:

namespace System {
  public static class Tuple {
    public static Tuple<T1> Create<T1>( T1 item1 );
    public static Tuple<T1 , T2> Create<T1, T2>( T1 item1 , T2 item2 );
    public static Tuple<T1 , T2 , T3> Create<T1, T2, T3>( T1 item1 , T2 item2 , T3 item3 );
    public static Tuple<T1 , T2 , T3 , T4> Create<T1, T2, T3, T4>( T1 item1 , T2 item2 , T3 item3 , T4 item4 );
     public static Tuple<T1 , T2 , T3 , T4 , T5> Create<T1, T2, T3, T4, T5>( T1 item1 , T2 item2 , T3 item3 , T4 item4 , T5 item5 );
     public static Tuple<T1 , T2 , T3 , T4 , T5 , T6> Create<T1, T2, T3, T4, T5, T6>( T1 item1 , T2 item2 , T3 item3 , T4 item4 , T5 item5 , T6 item6 );
     public static Tuple<T1 , T2 , T3 , T4 , T5 , T6 , T7> Create<T1, T2, T3, T4, T5, T6, T7>( T1 item1 , T2 item2 , T3 item3 , T4 item4 , T5 item5 , T6 item6 , T7 item7 );
     public static Tuple<T1 , T2 , T3 , T4 , T5 , T6 , T7 , Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>( T1 item1 , T2 item2 , T3 item3 , T4 item4 , T5 item5 , T6 item6 , T7 item7 , T8 item8 );
  }
}

這些多載的Create方法,可以讓你選擇儲存一到七個項目,Create<T1>,表示可以儲存一個項目;Create<T1, T2>方法則可以儲存兩個項目;若要儲存超過8個以上的項目,則可以使用第八個多載方法,利用第八個引數,來建立巢狀式的Tuple物件。接下來讓我們來看看Tuple的應用。

 

使用Tuple讓方法回傳多個值

C#的方法(Method)中只能夠回傳一個運算過的值,若要回傳多個值,可以將多個值放在陣列或集合一次回傳,或者使用out參數來解決這個問題。但這些做法都有些缺點,使用陣列或集合一次回傳多個值會額外花費一些搜尋其中項目的時間;使用out參數需要額外宣告、初始化out變數。且以上的做法都無法確保執行緒安全(Thread-Safe)。現在Tuple是另一種讓方法回傳多個值的選擇,並且具備執行緒安全的特性。

我們來看看Tuple的應用,例如以下範例程式碼,在GetData方法之中,利用Tuple類別的Create方法,建立可以儲存兩個數值項目的Tuple物件,並將之傳回:

 

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      Tuple<int , int> result = GetData( );
      Console.WriteLine( $"SUM = {result.Item1}" );
      Console.WriteLine( $"Count = {result.Item2}" );
    }
    static Tuple<int , int> GetData( ) {
      int [ ] data = { 1 , 8 , 52 , 45 , 12 , 44 , 75 , 68 , 24 , 59 };
      return Tuple.Create( data.Sum( ) , data.Count( ) );
    }
  }
}

 

上述的GetData()方法計算data陣列中數值的總合,以及個數,並利用Tuple將這兩個計算過的數值利用Tuple回傳。在Main方法中我們可以利用屬性的語法(使用「.」符號),來存取Tuple中的項目。若要存取Tuple中的第一個項目,可以使用Item1屬性;若存取Tuple中的第二個項目,可以使用Item2屬性,依此類推。此範例程式的執行結果,請參考下圖所示:

clip_image002

圖 1:使用Tuple儲存兩個數值範例執行結果。

使用new關鍵字建立Tuple實體

除了使用Tuple類別的Create靜態方法來建立Tuple物件之外,你也可以直接使用new關鍵字,來建立Tuple物件的實體,並利用建構函式初始化它的內容,例如我們可以將上述範例程式碼可以改寫如下,並可得到相同的執行結果:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      Tuple<int , int> result = GetData( );
      Console.WriteLine( $"SUM = {result.Item1}" );
      Console.WriteLine( $"Count = {result.Item2}" );
    }
    static Tuple<int , int> GetData( ) {
      int [ ] data = { 1 , 8 , 52 , 45 , 12 , 44 , 75 , 68 , 24 , 59 };
      return new Tuple<int , int>( data.Sum( ) , data.Count( ) );
    }
  }
}

 

儲存八個以上的項目

若要在Tuple中儲存八個以上的項目,可以建立巢狀式的Tuple結構,例如以下範例程式碼所示,GetData方法中建立並回傳一個Tuple<int , int , int , int , int , int , int , Tuple<int>>物件,建構函式的第一到七個引數是int型別,第八個引數則是一個Tuple<int>物件。在Main方法中,我們利用Tuple的Rest屬性來取得最後一個Tuple<int>>物件:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      Tuple<int , int , int , int , int , int , int , Tuple<int>> result = GetData( );
      Console.WriteLine( $"Item1 = {result.Item1}" );
      Console.WriteLine( $"Item2 = {result.Item2}" );
      Console.WriteLine( $"Item3 = {result.Item3}" );
      Console.WriteLine( $"Item4 = {result.Item4}" );
      Console.WriteLine( $"Item5 = {result.Item5}" );
      Console.WriteLine( $"Item6 = {result.Item6}" );
      Console.WriteLine( $"Item7 = {result.Item7}" );
      Console.WriteLine( $"Item8 = {result.Rest.Item1}" );
    }
    static Tuple<int , int , int , int , int , int , int , Tuple<int>> GetData( ) {
      return new Tuple<int , int , int , int , int , int , int , Tuple<int>>( 1 , 2 , 3 , 4 , 5 , 6 , 7 , new Tuple<int>( 8 ) );
    }
  }
}

 

此範例程式的執行結果,請參考下圖所示:

clip_image004

圖 2:使用Tuple儲存八個以上的項目。

以下是使用Static方法來儲存八個以上項目的範例:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      Tuple<int , int , int , int , int , int , int , Tuple<int>> result = GetData( );
      Console.WriteLine( $"Item1 = {result.Item1}" );
      Console.WriteLine( $"Item2 = {result.Item2}" );
      Console.WriteLine( $"Item3 = {result.Item3}" );
      Console.WriteLine( $"Item4 = {result.Item4}" );
      Console.WriteLine( $"Item5 = {result.Item5}" );
      Console.WriteLine( $"Item6 = {result.Item6}" );
      Console.WriteLine( $"Item7 = {result.Item7}" );
      Console.WriteLine( $"Item8 = {result.Rest.Item1}" );
    }
    static Tuple<int , int , int , int , int , int , int , Tuple<int>> GetData( ) {
      return Tuple.Create( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
    }
  }
}

 

使用Tuple物件當方法的參數傳遞

Tuple物件可以當做方法的參數來傳遞,這樣的好處是:你可以只宣告一個輸入參數,但可以傳遞不同個數與型別的資料到方法之中。這個設計比C# 語法的可變數目引數(params)來的方便,因為params參數限定只能使用相同的型別,而Tuple物件可以存放不同型別的資料。例如以下範例程式碼,建立一個可以存放兩個項目的Tuple物件,其中的第一個項目是數直型別;第二個項目則是字串型別:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      int [ ] data = { 1 , 8 , 52 , 45 , 12 , 44 , 75 , 68 , 24 , 59 };
      string s = $"Count = {data.Count( )}";
      Tuple<int , string> parm = Tuple.Create( data.Sum( ) , s );
      Print( parm );
    }
    static void Print( Tuple<int , string> p ) {
      Console.WriteLine( $"SUM = {p.Item1}" );
      Console.WriteLine( p.Item2 );
    }
  }
}

 

在Main方法中,我們將一個陣列中數值資料的總合,與一個字串打包在Tuple之中,並將之傳遞到Print方法之中。使用Tuple讓程式看起來更為簡潔。此範例程式的執行結果,請參考下圖所示:

clip_image006

圖 3:在Tuple物件儲存不同型別的資料。

再者,使用Tuple的好處是,它減少許多使用物件型別的Boxing與Unboxing的程序,使用強型別的方式來儲存資料,因此在開發工具之中,Visual Studio 便會自動提示Tuple其中項目的型別,例如上例的Item1會是數值型別(int),當你在Visual Studio 開發工具中,將滑鼠游標移動到變數上方,馬上就會顯示Tuple內項目的型別資訊;

clip_image008

圖 4:Visual Studio 開發工具自動辨識Tuple項目型別。

而Item2則是字串(string)型別:

clip_image010

圖 5:Visual Studio 開發工具自動辨識Tuple項目型別。

Tuple物件可以儲存特殊結構

我們可以在Tuple物件中儲存集合或陣列物件,來設計更特殊的資料結構,例如你同時想要儲存學生的姓名、年齡與興趣,興趣包含多種項目,你可以宣告如下的Tuple物件,利用List<string>來描述學生的興去有多個:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      var student = Tuple.Create(
       "Mary" ,
        28 ,
         new List<string>( ) { "walking" , "swimming" }
        );

      Console.WriteLine( student.Item1 );
      Console.WriteLine( student.Item2 );
      Console.WriteLine( "Interest :" );
      student.Item3.ForEach( s => Console.WriteLine( $"\t{s}" ) );
    }
  }
}

 

此範例程式的執行結果,請參考下圖所示:

clip_image012

圖 6:Tuple物件可以儲存特殊結構。

當然,你也可以自行設計一個類別來做到相同的事情,不過Tuple的好處是:它具備執行緒安全(Thread-Safe)的特性,你不需要煩惱這個問題。

在集合中儲存Tuple物件

我們也可以在集合之中儲存多個Tuple物件,例如以下範例程式碼,建立一個students集合,儲存Tuple<string , int , List<string>>型別的項目。利用集合的Add方法,加入多個Tuple物件到集合之中,最後使用foreach迴圈,將其中的項目的值印出:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      List<Tuple<string , int , List<string>>> students = new List<Tuple<string , int , List<string>>>( );

      students.Add( Tuple.Create(
       "Mary" ,
        28 ,
         new List<string>( ) { "walking" , "swimming" }
        ) );

      students.Add( Tuple.Create(
       "Candy" ,
        35 ,
         new List<string>( ) { "Playing video game" , "Climbing" }
        ) );

      foreach ( var item in students ) {
        Console.WriteLine( item.Item1 );
        Console.WriteLine( item.Item2 );
        Console.WriteLine( "Interest :" );
        item.Item3.ForEach( s => Console.WriteLine( $"\t{s}" ) );
        Console.WriteLine( "===============================" );
      }
    }
  }
}


 

此範例程式的執行結果,請參考下圖所示:

clip_image014

圖 7:在集合中儲存Tuple物件。

建立Tuple陣列

宣告Tuple陣列和宣告Tuple集合沒有什麼太大的不同,參考以下範例程式碼,建立三個Tuple<string>物件,儲存在陣列之中:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      Tuple<string> [ ] data = new Tuple<string> [ ] {
         Tuple.Create("Mary"),Tuple.Create("Candy"),Tuple.Create("Judy")
      };

      foreach ( Tuple<string> item in data ) {
        Console.WriteLine( item.Item1 );
      }
    }
  }
}


 

此範例程式的執行結果,請參考下圖所示:

clip_image016

圖 8:建立Tuple陣列。

排序Tuple項目

最後我們談談排序的問題,若要對集合或陣列中的項目進行排序,可以利用OrderBy(由小到大)或OrderByDescending(由大到小)擴充方法。以下範例程式碼,叫用OrderBy方法,根據學生的名稱排序,由小排到大,再利用for each 迴圈將其中的學生資料一一印出:

namespace TupleDemo {
  class Program {
    static void Main( string [ ] args ) {
      List<Tuple<string , int , List<string>>> students = new List<Tuple<string , int , List<string>>>( );

      students.Add( Tuple.Create(
       "Mary" ,
        28 ,
         new List<string>( ) { "walking" , "swimming" }
        ) );

      students.Add( Tuple.Create(
       "Candy" ,
        35 ,
         new List<string>( ) { "Playing video game" , "Climbing" }
        ) );

      foreach ( var item in students.OrderBy( t => t.Item1 ) ) {
        Console.WriteLine( item.Item1 );
        Console.WriteLine( item.Item2 );
        Console.WriteLine( "Interest :" );
        item.Item3.ForEach( s => Console.WriteLine( $"\t{s}" ) );
        Console.WriteLine( "===============================" );
      }
    }
  }
}


 

此範例程式的執行結果,請參考下圖所示:

clip_image018

圖 9:排序Tuple項目。

目前評分 5.0 , 共有 2 人參與

  • Currently 5.0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET Magazine國際中文電子雜誌 | C# | .NET Framework | 許薰尹Vivid Hsu

評論 (48) -

cours de theatre paris
cours de theatre paris United States
2017/10/1 上午 02:45:57 #

Muchos Gracias for your post.

can ho vung tau
can ho vung tau United States
2017/10/7 上午 01:49:59 #

Really enjoyed this blog article.Much thanks again. Cool.

Osimi sea view
Osimi sea view United States
2017/10/9 下午 07:37:54 #

I really liked your blog article. Awesome.

see
see United States
2017/10/14 下午 05:32:21 #

Really enjoyed this blog post.Thanks Again. Will read on...

dragon city hack pc
dragon city hack pc United States
2017/10/15 下午 05:03:20 #

Thank you for your blog.Really looking forward to read more. Fantastic.

Discover More Here
Discover More Here United States
2017/10/17 下午 04:21:40 #

Major thanks for the blog article.Much thanks again. Really Cool.

sex pill
sex pill United States
2017/10/19 上午 08:56:47 #

Thanks a lot for the blog.Much thanks again. Great.

this hyperlink
this hyperlink United States
2017/10/19 下午 08:02:29 #

Thanks again for the article.Much thanks again. Great.

carte grise en ligne
carte grise en ligne United States
2017/10/21 上午 09:00:53 #

Major thankies for the blog. Great.

phentaslim review
phentaslim review United States
2017/11/3 上午 08:02:33 #

I truly appreciate this blog.Thanks Again. Awesome.

back pain fitness inspiration
back pain fitness inspiration United States
2017/11/15 上午 07:10:49 #

Wow, great post. Want more.

avocat criminel montreal
avocat criminel montreal United States
2017/11/16 下午 05:46:13 #

Very informative article post.Much thanks again.

Wow, great article.Really thank you! Want more.

gain more followers twitter
gain more followers twitter United States
2017/11/22 上午 02:20:33 #

Thanks for sharing, this is a fantastic blog article.Really looking forward to read more. Fantastic.

swimwear
swimwear United States
2017/11/23 下午 09:12:50 #

Thanks again for the blog article.Really thank you! Really Cool.

Search Engine Optimisation Nz
Search Engine Optimisation Nz United States
2017/11/25 下午 06:11:24 #

I value the blog post.Much thanks again. Will read on...

Chad Boonswang and Jeffrey Goodman
Chad Boonswang and Jeffrey Goodman United States
2017/11/26 下午 05:21:39 #

I think this is a real great blog.Thanks Again. Great.

Chad Boonswang SEO
Chad Boonswang SEO United States
2017/11/26 下午 11:22:37 #

Really enjoyed this article post. Will read on...

cash for old car
cash for old car United States
2017/11/29 下午 03:47:26 #

Major thankies for the post.Really thank you! Cool.

can ho quan quan 8
can ho quan quan 8 United States
2017/11/29 下午 10:22:02 #

I really enjoy the blog article.Thanks Again. Awesome.

business trade lines
business trade lines United States
2017/12/1 上午 12:13:25 #

Thanks-a-mundo for the article post. Awesome.

porno
porno United States
2017/12/1 下午 03:52:51 #

Really enjoyed this blog.Really thank you! Fantastic.

commercial real estate loan
commercial real estate loan United States
2017/12/3 上午 04:12:05 #

I really liked your blog.Much thanks again. Will read on...

Major thanks for the article post.Really thank you! Really Great.

http://yesgamingious.download/story/11707
http://yesgamingious.download/story/11707 United States
2017/12/10 上午 08:12:28 #

Major thanks for the article post.Really looking forward to read more. Really Great.

george laws
george laws United States
2017/12/10 下午 06:36:35 #

Enjoyed every bit of your article. Fantastic.

Jenniffer Eberheart
Jenniffer Eberheart United States
2017/12/14 上午 08:44:06 #

I value the blog.Thanks Again. Really Great.

Christmas
Christmas United States
2017/12/14 下午 10:05:41 #

Very neat post. Great.

canon drivers
canon drivers United States
2017/12/16 下午 05:17:34 #

A big thank you for your blog.Really looking forward to read more. Keep writing.

tips weight loss
tips weight loss United States
2017/12/16 下午 11:33:30 #

Very good blog post.Much thanks again. Great.

Thanks so much for the blog.Thanks Again. Really Great.

Mid-market
Mid-market United States
2017/12/17 下午 04:58:55 #

Really enjoyed this post.Thanks Again. Keep writing.

degreeshortcut
degreeshortcut United States
2017/12/18 上午 12:00:48 #

I value the blog post.Much thanks again. Cool.

income from home
income from home United States
2017/12/20 下午 06:10:23 #

Thanks-a-mundo for the article.Really looking forward to read more.

canon drivers
canon drivers United States
2017/12/23 上午 05:29:14 #

Thanks-a-mundo for the blog.Really looking forward to read more. Fantastic.

Darwin Horan
Darwin Horan United States
2017/12/23 下午 03:57:32 #

This is one awesome article post.Really thank you! Much obliged.

hp driver
hp driver United States
2017/12/25 下午 05:31:29 #

Thank you ever so for you post.

&#216;&#177;&#218;&#175; &#216;&#174;&#217;ˆ&#216;&#167;&#216;&#168;
رگ خواب United States
2017/12/26 上午 12:16:39 #

Major thanks for the article post.Much thanks again. Want more.

Very informative blog post.Much thanks again. Will read on...

canon drivers
canon drivers United States
2017/12/27 下午 09:05:45 #

I truly appreciate this blog.Much thanks again. Cool.

hp drivers
hp drivers United States
2018/1/2 上午 11:40:03 #

wow, awesome post.Really thank you! Really Great.

Epson drivers
Epson drivers United States
2018/1/3 上午 11:01:28 #

Great, thanks for sharing this article post.Thanks Again. Great.

best Bitcoin casinos
best Bitcoin casinos United States
2018/1/4 下午 09:49:54 #

I think this is a real great blog. Awesome.

hp printer driver
hp printer driver United States
2018/1/5 下午 05:57:14 #

Fantastic post.Really looking forward to read more. Cool.

FBA
FBA United States
2018/1/6 上午 10:03:32 #

I truly appreciate this blog post. Great.

colocation chicago
colocation chicago United States
2018/1/10 上午 09:58:26 #

Great blog post.Much thanks again. Will read on...

c7UrqEjZLWoZ
c7UrqEjZLWoZ United States
2020/11/26 上午 11:49:32 #

984145 335632Hello there, just became alert to your blog via Google, and discovered that it�s truly informative. I�m going to watch out for brussels. I will appreciate in the event you continue this in future. Numerous individuals will probably be benefited from your writing. Cheers! 731350

NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List