C#Tuples(元組)

來源:互聯網
上載者:User

1. 老版本代碼


 1 class Program 2 { 3     static void Main(string[] args) 4     { 5         var fullName = GetFullName(); 6  7         Console.WriteLine(fullName.Item1);// Item1,2,3不能忍,,, 8         Console.WriteLine(fullName.Item2); 9         Console.WriteLine(fullName.Item3);10     }11     static Tuple<string, string, string> GetFullName() => new Tuple<string, string, string>("first name", "blackheart", "last name");12 }

在有些情境下,我們需要一個方法返回一個以上的傳回值,微軟在.NET 4中引入了Tuple這個泛型類,可以允許我們返回多個參數,每個參數按照順序被命名為 Item1;Item2,Item3 ,算是部分的解決了我們的問題,但是對於強迫症程式員來說,Item1,2,3的命名簡直是不能忍的,,,so,在C#7中,引入了一個新的泛型型別ValueTuple<T>來解決這個問題,這個類型位於一個單獨的dll(System.ValueTuple)中,可以通過nuget來引入到你當前的項目中(http://www.php.cn/)。

2. ValueTuple

不廢話,直接看代碼:


 1 class Program 2 { 3     static void Main(string[] args) 4     { 5         var fullName = GetFullName(); 6  7         Console.WriteLine(fullName.First);  // 終於可以不是Item1,2,3了,,, 8         Console.WriteLine(fullName.Middle); 9         Console.WriteLine(fullName.Last);10     }11 12     static (string First, string Middle, string Last) GetFullName() => ("first name", "blackheart", "last name");13 }

看出來差別了嗎?我們終於可以用更直觀的名字來替換掉該死的"Item1,2,3"了,看起來很棒吧。但是貌似我們並沒有用到上面我提到的System.ValueTuple,我們翻開編譯後的程式集看看:


 1 internal class Program 2 { 3     private static void Main(string[] args) 4     { 5         ValueTuple<string, string, string> fullName = Program.GetFullName(); 6         Console.WriteLine(fullName.Item1); // 原來你還是Item1,2,3,,,FUCK!!! 7         Console.WriteLine(fullName.Item2); 8         Console.WriteLine(fullName.Item3); 9     }10 11     [TupleElementNames(new string[]12     {13             "First",14             "Middle",15             "Last"16     })]17     private static ValueTuple<string, string, string> GetFullName()18     {19         return new ValueTuple<string, string, string>("first name", "blackheart", "last name");20     }21 }

不看不知道,一看嚇一跳,原來我們的 fullName.First; 編譯後居然還是 fullName.Item1 ,真是日了狗了。。。

不同之處在於GetFullName這個方法,編譯器把我們簡化的文法形式翻譯成了 ValueTuple<string, string, string> ,還給加了一個新的Attribute(TupleElementNamesAttribute),然後把我們自訂的非常直觀友好的“First”,"Middle","Last"當作中繼資料給存起來了(如果只是局部使用,則不會添加這樣的中繼資料)。TupleElementNamesAttribute和ValueTuple一樣,位於System.ValueTuple的單獨dll中。

3. Example


 1 class Program 2 { 3     static void Main(string[] args) 4     { 5         var range = (first: 1, end: 10); 6         //也可以這樣寫,效果是一樣的,編譯後都是沒有了first,end的痕迹,,,first和end只是文法層面的障眼法 7         //(int first, int last) range = (1, 10); 8         Console.WriteLine(range.first); 9         Console.WriteLine(range.end);10 11         //可以使用var,這種無顯示聲明一個變數的方式會編譯出多餘的代碼,慎用,不知是不是還未最佳化好。12         (var begin, var end) = (DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31"));13         Console.WriteLine(begin);14         Console.WriteLine(end);15 16         //begin,end可以被覆蓋重新命名為startDate和endDate,但是會有一個編譯警告,提示名字被忽略掉了。17         //warning CS8123: The tuple element name 'begin' is ignored because a different name is specified by the target type '(DateTime startDate, DateTime endDate)'18         //warning CS8123: The tuple element name 'end' is ignored because a different name is specified by the target type '(DateTime startDate, DateTime endDate)‘19         (DateTime startDate, DateTime endDate) timeSpan = (begin: DateTime.Parse("2017-1-1"), end: DateTime.Parse("2017-12-31"));20         Console.WriteLine(timeSpan.startDate);21         Console.WriteLine(timeSpan.endDate);22     }23 }

look一下編譯後的代碼:


 1 private static void Main(string[] args) 2 { 3     ValueTuple<int, int> range = new ValueTuple<int, int>(1, 10); 4     Console.WriteLine(range.Item1); 5     Console.WriteLine(range.Item2); 6     ValueTuple<DateTime, DateTime> expr_3C = new ValueTuple<DateTime, DateTime>(DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31")); 7     DateTime item = expr_3C.Item1; 8     DateTime item2 = expr_3C.Item2; 9     DateTime begin = item;10     DateTime end = item2;11     Console.WriteLine(begin);12     Console.WriteLine(end);13     ValueTuple<DateTime, DateTime> timeSpan = new ValueTuple<DateTime, DateTime>(DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31"));14     Console.WriteLine(timeSpan.Item1);15     Console.WriteLine(timeSpan.Item2);16 }

注意 (var begin, var end) = (DateTime.Parse("2017-1-1"), DateTime.Parse("2017-12-31")); 這一行的便宜結果,看起來很是糟糕(上述6-10行紅色部分),可能還是編譯最佳化不足的問題吧(release編譯也是如此)。

4. 總結

新的文法形式確實直觀友好了好多,but,本質依然是藉助泛型型別來實現的,同時也需要編譯器對新文法形式的支援。

瞭解了本質是什麼東西之後,以後在項目中環境允許的話,就放心大膽的使用吧(類型ValueTuple可以出現的地方,(first,last)這種新文法形式均可以)。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.