1. 程式人生 > >C♯ 7 中的 Tuple 特性

C♯ 7 中的 Tuple 特性

介紹

Tuple是異類物件的有序序列。 我們經常可以寫出返回多個值的方法,所以我們需要建立一個包含多個數據元素的簡單結構。 為了支援這些情況,Tuple 被新增到 C#。 Tuple 是包含多個欄位用來表示資料成員的輕量級資料結構。

如果一個方法返回多個相同型別的數值,那麼它可以將這些值儲存在一個集合中並返回該集合。 但是如果一個方法需要返回多個不同型別的值呢,C# 提供了一些可選項,比如 Class / Struct,輸出引數和 Tuple。

讓我們建立一個示例。 我們有一個整數的集合,而且我們需要從這個集合中找出的最小值和最大值。 這時候我們需要建立一個返回最小值和最大值的方法。 為了實現這一點,我們有三個選項:Class / Struct,輸出引數和 Tuple。  那麼,讓我們逐個看看每個選項是如何完成這一功能的。

使用 out 引數

當我們建立一個方法,找出數字序列中的最大值和最小值。 該方法需要將兩個值作為最大值和最小值的結果。 因此,我們建立返回值和使用 out 引數作為引數的方法。 返回值儲存系列中的最大數,而 out 引數儲存系列中的最小數。

讓我們建立一個名為 Operation 的類,它實現一個從數字系列中查詢最小和最大數的方法。 以下程式碼段就能實現該功能。

12345678910111213141516171819 using System.Collections.Generic;namespaceTupleApp{classOperation{internal intFindMinMax(List<int>list,out intmin){intmaximum=int.MinValue,minimum=int.MaxValue;list.ForEach(n=>{minimum=n<minimum?n:minimum;maximum=n>
maximum?n:maximum;});min=minimum;returnmaximum;}}}

根據上述程式碼片段,該方法返回一個值,該值儲存一個名為 maximum 的整形變數。 該值是該系列的最大值。 此方法將輸出引數是名為 min 的引數,該引數儲存的是系列中的最小值。

現在,根據下面的程式碼片段從可執行程式呼叫此方法。

1234567891011121314151617181920 using System;using System.Collections.Generic;using System.Linq;using staticSystem.Console;namespaceTupleApp{classProgram{staticvoidMain(string[]args){List<int>numbers=Enumerable.Range(1,100).OrderBy(x=>Guid.NewGuid()).Take(10).ToList();intminimum=0,maximum=0;Operation operation=newOperation();maximum=operation.FindMinMax(numbers,out minimum);Write($"{minimum} is min and {maximum} is max in {String.Join(",", numbers)}");Read();}}}

現在,執行應用程式。 結果如下圖所示。

圖1:輸出

這是正確的方法,但 out 引數並不適合於非同步方法。

使用 Class/Struct

還有另一個選項可以從一個方法獲取多個值–建立一個具有該資料結構的類或結構體。 我們在這裡也執行相同的操作。 我們建立一個名為 CalculateData 的結構體,這個結構體中有兩個屬性來儲存一個系列的最大值和最小值。 以下程式碼段就是用來建立這個結構體。

12345678 namespaceTupleApp{structCalculateData{publicintMinimum{get;set;}publicintMaximum{get;set;}}}

現在,讓我們建立另一個名為 Operation 的類,它用來實現從數字序列中查詢最小值和最大值的方法。 以下程式碼段就是用來實現這一功能。

1234567891011121314151617181920212223 using System.Collections.Generic;namespaceTupleApp{classOperation{internal CalculateData FindMinMax(List<int>list){intmaximum=int.MinValue,minimum=int.MaxValue;list.ForEach(n=>{minimum=n<minimum?n:minimum;maximum=n>maximum?n:maximum;});CalculateData data=newCalculateData{Minimum=minimum,Maximum=maximum};returndata;}}}

根據上面的程式碼片段,該方法返回一個具有兩個屬性的物件。 這些屬性裡儲存的是系列中的最大值和最小值。
現在,從可執行程式呼叫此方法,如下面的程式碼片段所示。

12345678910111213141516171819 using System;using System.Collections.Generic;using System.Linq;using staticSystem.Console;namespaceTupleApp{classProgram{staticvoidMain(string[]args){List<int>numbers=Enumerable.Range(1,100).OrderBy(x=>Guid.NewGuid()).Take(10).ToList();Operation operation=newOperation();CalculateData data=operation.FindMinMax(numbers);Write($"{data.Minimum} is min and {data.Maximum} is max in {String.Join(",", numbers)}");Read();}}}

現在,執行應用程式。 最終結果如下圖所示。

圖2: 輸出結果

使用 Tuple

C#7 引入了定義元組的新方法。 Tuple 是從方法返回多個值的另一個選擇。 它可以儲存多個不同型別的值。 要在應用程式中使用 Tuple,我們需要安裝 System.ValueTuple NuGet 包.

圖3 NuGet 包

我們在這裡也執行相同的操作。 讓我們建立一個名為 Operation 的類,它實現一個從數字系列中查詢最小值和最大數的方法。 以下程式碼段用來實現該功能。

123456789101112131415161718 using System.Collections.Generic;namespaceTupleApp{classOperation{internal(int,int)FindMinMax(List<int>list){intmaximum=int.MinValue,minimum=int.MaxValue;list.ForEach(n=>{minimum=n<minimum?n:minimum;maximum=n>maximum?n:maximum;});return(minimum,maximum);}}}

根據上面的程式碼片段,該方法返回一個有兩個專案的元組。 這些專案儲存數字系列的最大值和最小值。

現在,根據下面的程式碼片段在可執行程式呼叫這個方法。

12345678910111213141516171819 using System;using System.Collections.Generic;using System.Linq;using staticSystem.Console;namespaceTupleApp{classProgram{staticvoidMain(string[]args){List<int>numbers=Enumerable.Range(1,100).OrderBy(x=>Guid.NewGuid()).Take(10).ToList();Operation operation=newOperation();(int,int)data=operation.FindMinMax(numbers);Write($"{data.Item1} is min and {data.Item2} is max from {String.Join(",", numbers)}");Read();}}}

根據上面的程式碼片段,名為 FindMinMax 的方法呼叫並返回一個元組。 當方法直接返回多個值到一個 Tuple 型別,它們會按照他們的順序給它們一些預設名稱,以便可以方便地呼叫它們。這元組有兩個專案,因此這些專案呼叫 Item1 和 Item2。 Item1 表示第一個值,而 Item2 表示第二個值。這跟 Tupple 項在建立時使用的順序相同。

現在,執行應用程式。 最終結果如下圖所示。

圖4 輸出結果

由於 Item1 和 Item2 不表示欄位的實際名稱,因此我們可以給它們自定義名稱。 元組型別變數可以具有自定義名稱,而不是僅僅是預設的 Item1 或 Item2。

讓我們更新 Operation 類中名為 FindMinMax 的現有方法。 我們為這些元組欄位分配自定義名稱。 以下程式碼段用來實現該功能。

123456789101112131415161718 using System.Collections.Generic;namespaceTupleApp{classOperation{internal(intMinimum,intMaximum)FindMinMax(List<int>list){intmaximum=int.MinValue,minimum=int.MaxValue;list.ForEach(n=>{minimum=n<minimum?n:minimum;maximum=n>maximum?n:maximum;});return(minimum,maximum);}}}

這裡,元組的第一個欄位名稱為 Minimum,而另一個欄位名為 Maximum。

現在,根據下面的程式碼片段從可執行程式呼叫此方法。