Tuple Tuesday!

在不久的將來,我們試圖將 Tuple 作為一項核心功能加入到 VB 和 C# 中。如果您還沒有聽說 Tuple,那可以將它理解為是一種把多種值組合在一起的基礎資料結構。像 .NET 裡面的 F#, 有許多編程語言已支持它多年,然而在 Visual Basic 中不支援確實有些奇怪了。Tuple 就像陣列一樣,它是一個捆綁了多個值作為一個單元,而陣列中每個元素都是相同的類型,但在 Tuple 中每個元素可以有不同的類型。所以,如果我發現在我的程序中,我總是需要同時傳兩個值,那麼我就可以把它們組合成一個 Tuple:

 

不使用 Tuple 的情況:

Sub Method1(x As Integer, y As Integer)
    ‘ Do something.
    Method2(x, y)
End Sub

Sub Method2(x As Integer, y As Integer)
    ‘ Do other stuff.
End Sub

 

使用 Tuple 的情況:

Sub Method1(point As Tuple(Of Integer, Integer))
    ‘ Do something.
    Method2(point)
End SubSub Method2(point As (Integer, Integer))
    ‘ Do other stuff.
End Sub

 

在上面的例子中,我們可以用包含 2 個整數的 Tuple 作為方法的參數,而不是在方法之間單獨傳遞兩個整數參數。這樣能使我們更加清楚的知道這些值被作為一個單元來處理。在本例中我使用了存在於 .NET 4.0 及以上版本裡的通用 Tuple 類型 System.Tuple(of T1,T2)。您今天也可以這樣使用,只是有兩個缺點。第一,System.Tuple(of T1,T2)以及和它關聯的類型都是類別,因此每次您創建一個 Tuple(of T1,T2)類型,它都會在堆上分配的一個新的對象。在VB和C#中,我們正在考慮使用一套新的值類型的 Tuple 類型,如 ValueType(Of T1, T2)分配內聯地址,這樣更方便於使用元組。第二,在收到大量關於 Tuple 名稱有多重要的客戶回饋後,內置 VB(和 C#)Tuple 將具有名稱:

 

Sub Method1(point As (X As Integer, Y As Integer))
    ‘ Do something.
    Console.WriteLine($”X={point.X}, Y={point.Y}“)
End Sub

 

這意味著您將擁有所有宣告自己結構但帶有輕量語法的自文檔化名稱。這有點類似於 VB 裡的匿名類型,同時可以在方法外傳值。這使得 VB Tuple 具有了像 F# 語言中 Tuple 和記錄的所有特點。我們覺得這簡直太完美了。

儘管簡潔,但僅僅一起傳遞多個數據並不會太有吸引力,對於 Tuple 最耀眼的部分是回傳多個值。如果沒有 Tuple 您需要寫這樣一種方法,將兩個數相除並回傳商和餘數:

 

”’ <Summary>Divides two integers and returns the quotient and remainder.</Summary>
Function DivRem(dividend As Integer, divisor As Integer, ByRef remainder As Integer) As Integer
    remainder = dividend Mod divisor
    Return dividend \ divisor
End Function

 

因為 VB 函數總是精確的回傳一個值,如果您想要回傳額外的值就需要在調用方法中傳遞 ByRef 變數。或者,您自己可以在您的程式碼中宣告 QuotientAndRemainder 結構,但老實說又有誰想要在自己的項目中,為了一個回傳值,創建一個名字有些滑稽的方法類型呢?如果有了 Tuple,您就不需要考量這些:

 

”’ <Summary>Divides two integers and returns the quotient and remainder.</Summary>
Function DivRem(dividend As Integer, divisor As Integer) As (divisor As Integer, remainder As Integer)
    Return (dividend \ divisor, dividend Mod divisor)
End Function

 

作為一種語言,它的目標是可讀的和易理解的,我認為這是到目前為止最簡單和最直接的方式去從一個函數回傳多個值。我們認為 Tuple 的使用,極大地方便了在專案裡傳遞和回傳多個值。當使用強大的非同步功能時,這個優勢更加突出,因為在非同步函數中您甚至不能有 ByRef 參數。今天您將需要宣告一個特殊的結構,或使用陣列(如果所有的值都具有相同的類型),或者使用 Tuple 類型卻丟掉有意義的名稱。使用 Tuple,您可以擁有所有的方便之處。

 

”’ <Summary>Asynchronously enumerates all orders in the database for the month and calculates the total value of the orders, the average order value, and total number of orders.</Summary>
Async Function CalculateMonthlyTotalsAsync() As Task(Of (total As Decimal, average As Decimal, count As Integer))

 

此方法透過網絡從數據庫中提取一些數據,所以它應該是非同步的並且遍歷所有的訂單來計算有用的統計資訊,如所有訂單的總值,平均訂單數和訂單的數量。如果沒有 Tuple 您將不得不在您的項目中添加一個非常討厭的 TotalAverageAndCount 類型。

目前,關於在 Visual Basic 中 Tuple 的完整設計策略,可以透過閱讀 design notes on GitHub 來了解,包括用一些其他方式將 Tuple 集成到其它語言中。請在 GitHub 中留下關於 Tuple 功能設計上的回饋或者在下面進行評論。

上週,我絞盡腦汁地想提出一個好的雙關語來介紹 Tuple,導致這篇文章會比原計劃晚了一周。 「Tuple Tuesday」算是一個較好的選擇吧!為了避免混淆,VB 語言設計團隊為正在添加的那些功能積極集思廣益出了許多雙關語。我認為下一個設計主題將是「Visual Basic and Patterns – A Match Made In Heaven!」 (我認為這將給 VB 添加一個全新的維度)-敬請期待。在此之前,依舊快樂 coding 吧!

 

Regard,

ADG

 

本文翻譯自 Tuple Tuesday!


 

Capture 1 Capture

 

若對以上技術及產品有任何問題,很樂意為您服務! 請洽:台灣微軟開發工具服務窗口 – MSDNTW@microsoft.com / 02-3725-3888 #4922