Visual Studio 2017 將在下個月初發行第一個對外正式版本,相關的工具也會一併釋出,其中包含 C# 7.0.在 C# 7.0 中有些新的簡便語法讓開發者可以打字少一點.在這些新功能中,Tuple 多了一個新兄弟,而且是一個 value type,所以叫做 ValueTuple.這篇文章將簡單地介紹 ValueTuple.
舊的 Tuple 是 reference type,當你要使用它時,便需要 new 一個 Tuple 物件,然後把值放進去,下面的例子就是一個傳統的 Tuple 例子.
static void Main(string[] args)
{
int[] numbers = { 1, 2 };
Tuple<double, double> result = CalSumAndAvg(numbers);
Console.WriteLine($"sum = {result.Item1}");
Console.WriteLine($"avg = {result.Item2}");
Console.ReadKey();
}
static Tuple<double, double> CalSumAndAvg(int[] numbers)
{
double sum = 0;
double avg;
for (int i = 0; i < numbers.Length; i++)
{
sum += numbers[i];
}
avg = sum / numbers.Length;
return new Tuple<double, double>(sum, avg);
}
我個人並不喜歡用 Tuple,因為存取內容時得用 Item1, Item2 這種名稱,用起來有點蠢,看起來也很好笑,因為記不起來 Item1, Item2 是什麼東西.假設你用了它,我相信過一段時間後,你也會忘了你當初寫的 Item1 , Item2 是什麼.通常都需要把前後的程式碼看完才知道 Item1, Item2 代表什麼東西.在新的 Tuple 中,這點可以克服了.為了要使用新的 Tuple,必須從 NuGet 上下載 System.ValueTuple.
首先, 可以把 Tuple<double, double> 直接改成 (double, double),而且新版的 Tuple 是 value type,所以不需要建立 Tuple 物件.
因為,上述的 CalSumAndAvg 可以改成如下:
static (double, double) CalSumAndAvg(int[] numbers)
{
double sum = 0;
double avg;
for (int i = 0; i < numbers.Length; i++)
{
sum += numbers[i];
}
avg = sum / numbers.Length;
return (sum, avg);
}
在原本的 Main 也能改成如下:
static void Main(string[] args)
{
int[] numbers = { 1, 2 };
(double,double) result = CalSumAndAvg(numbers);
Console.WriteLine($"sum = {result.Item1}");
Console.WriteLine($"avg = {result.Item2}");
Console.ReadKey();
}
接下來,為了要擺脫前面所說的 Item1, Item2,在使用 ValueTuple 時,你可以直接設定每個 item 的名稱,然後在操作該 tuple 時,就可以直接用設定好的名字做為 property,如下所示:
static void Main(string[] args)
{
int[] numbers = { 1, 2 };
(double Sum, double Avg) result = CalSumAndAvg(numbers);
Console.WriteLine($"sum = {result.Sum}");
Console.WriteLine($"avg = {result.Avg}");
Console.ReadKey();
}
從上面看起來,用 Sum, Avg 來做為 property name 比起 Item1, Item2 好多了.
以此類推的想法,你也可以設定一個初始值給 ValueTuple,同時設定每個 item 的名字,然後直接用名字去操作 property,如下所示:
static (double, double) CalSumAndAvg(int[] numbers)
{
var data = (s: 0.0, a: 0.0);
for (int i = 0; i < numbers.Length; i++)
{
data.s += numbers[i];
}
data.a = data.s / numbers.Length;
return data;
}
如果你喜歡用 Tuple 的話,相信這個 ValueTuple 會是你較喜歡的版本.同時,由於 ValueTuple 是 value type,所以它使用的記憶體空間不會在 managed heap,而是在 program stack 裡,因此使用 ValueTuple 不會有 garbage collection 在它身上發生.
ValueTuple 的原始程式碼在 https://github.com/dotnet/corefx/blob/master/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs
Hope it helps,