30分鐘掌握 C#7

1.?out 變量(out variables)

? 以前我們使用out變量必須在使用前進行聲明,C# 7.0 給我們提供了一種更簡潔的語法 “使用時進行內聯聲明” 。如下所示:

1   var input = ReadLine();
2   if (int.TryParse(input, out var result))
3   {
4       WriteLine("您輸入的數字是:{0}",result);
5   }
6   else
7   {
8       WriteLine("無法解析輸入...");
9   }

? 上面代碼編譯后:

 1   int num;
 2   string s = Console.ReadLine();
 3   if (int.TryParse(s, out num))
 4   {
 5       Console.WriteLine("您輸入的數字是:{0}", num);
 6   }
 7   else
 8   {
 9       Console.WriteLine("無法解析輸入...");
10   }

?原理解析:所謂的 “內聯聲明” 編譯后就是以前的原始寫法,只是現在由編譯器來完成。

?備注:在進行內聯聲明時,即可直接寫明變量的類型也可以寫隱式類型,因為out關鍵字修飾的一定是局部變量。

2. 元組(Tuples)

?元組(Tuple)在 .Net 4.0 的時候就有了,但元組也有些缺點,如:

? ?1)Tuple 會影響代碼的可讀性,因為它的屬性名都是:Item1,Item2.. 。

? ?2)Tuple 還不夠輕量級,因為它是引用類型(Class)。

? ?備注:上述所指 Tuple 還不夠輕量級,是從某種意義上來說的或者是一種假設,即假設分配操作非常的多。

?C# 7 中的元組(ValueTuple)解決了上述兩個缺點:

? ?1)ValueTuple 支持語義上的字段命名。

? ?2)ValueTuple 是值類型(Struct)。

?1. 如何創建一個元組?

1   var tuple = (1, 2);                           // 使用語法糖創建元組
2   var tuple2 = ValueTuple.Create(1, 2);         // 使用靜態方法【Create】創建元組
3   var tuple3 = new ValueTuple<int, int>(1, 2);  // 使用 new 運算符創建元組
4   
5   WriteLine($"first:{tuple.Item1}, second:{tuple.Item2}, 上面三種方式都是等價的。");

?原理解析:上面三種方式最終都是使用 new 運算符來創建實例。

?2. 如何創建給字段命名的元組?

 1   // 左邊指定字段名稱
 2   (int one, int two) tuple = (1, 2);
 3   WriteLine($"first:{tuple.one}, second:{tuple.two}");
 4   
 5   // 右邊指定字段名稱
 6   var tuple2 = (one: 1, two: 2);
 7   WriteLine($"first:{tuple2.one}, second:{tuple2.two}");
 8   
 9   // 左右兩邊同時指定字段名稱
10   (int one, int two) tuple3 = (first: 1, second: 2);    /* 此處會有警告:由于目標類型(xx)已指定了其它名稱,因為忽略元組名稱xxx */
11   WriteLine($"first:{tuple3.one}, second:{tuple3.two}");

?注:左右兩邊同時指定字段名稱,會使用左邊的字段名稱覆蓋右邊的字段名稱(一一對應)。?

?原理解析:上述給字段命名的元組在編譯后其字段名稱還是:Item1, Item2...,即:“命名”只是語義上的命名。

?3. 什么是解構?

?解構顧名思義就是將整體分解成部分。

?4. 解構元組,如下所示:

1   var (one, two) = GetTuple();
2   
3   WriteLine($"first:{one}, second:{two}");
1   static (int, int) GetTuple()
2   {
3       return (1, 2);
4   }

?原理解析:解構元組是將元組中的字段值賦值給聲明的局部變量(編譯后可查看)

?備注:在解構時“=”左邊能提取變量的數據類型(如上所示),元組中字段類型相同時即可提取具體類型也可以是隱式類型,但元組中字段類型

?不相同時只能提取隱式類型。

?5. 解構可以應用于 .Net 的任意類型,但需要編寫?Deconstruct 方法成員(實例或擴展)。如下所示:

 1   public class Student
 2   {
 3       public Student(string name, int age)
 4       {
 5           Name = name;
 6           Age = age;
 7       }
 8   
 9       public string Name { get; set; }
10   
11       public int Age { get; set; }
12   
13       public void Deconstruct(out string name, out int age)
14       {
15           name = Name;
16           age = Age;
17       }
18   }

?使用方式如下:

1   var (Name, Age) = new Student("Mike", 30);
2   
3   WriteLine($"name:{Name}, age:{Age}");

?原理解析:編譯后就是由其實例調用?Deconstruct 方法,然后給局部變量賦值。

?Deconstruct 方法簽名:

1   // 實例簽名
2   public void Deconstruct(out type variable1, out type variable2...)
3   
4   // 擴展簽名
5   public static void Deconstruct(this type instance, out type variable1, out type variable2...)

?總結:1. 元組的原理是利用了成員類型的嵌套或者是說成員類型的遞歸。2. 編譯器很牛B才能提供如此優美的語法。

  使用 ValueTuple 則需要導入: Install - Package System.ValueTuple

3.?模式匹配(Pattern matching)

?1. is 表達式(is expressions),如:

 1   static int GetSum(IEnumerable<object> values)
 2   {
 3       var sum = 0;
 4       if (values == null) return sum;
 5   
 6       foreach (var item in values)
 7       {
 8           if (item is short)     // C# 7 之前的 is expressions
 9           {
10               sum += (short)item;
11           }
12           else if (item is int val)  // C# 7 的 is expressions
13           {
14               sum += val;
15           }
16           else if (item is string str && int.TryParse(str, out var result))  // is expressions 和 out variables 結合使用
17           {
18               sum += result;
19           }
20           else if (item is IEnumerable<object> subList)
21           {
22               sum += GetSum(subList);
23           }
24       }
25   
26       return sum;
27   }

?使用方法:

1   條件控制語句(obj is type variable)
2   {
3      // Processing...
4   }

?原理解析:此 is 非彼 is ,這個擴展的 is 其實是 as 和 if 的組合。即它先進行 as 轉換再進行 if 判斷,判斷其結果是否為 null,不等于 null 則執行

?語句塊邏輯,反之不行。由上可知其實C# 7之前我們也可實現類似的功能,只是寫法上比較繁瑣。

?2. switch語句更新(switch statement updates),如:

 1   static int GetSum(IEnumerable<object> values)
 2   {
 3       var sum = 0;
 4       if (values == null) return 0;
 5   
 6       foreach (var item in values)
 7       {
 8           switch (item)
 9           {
10               case 0:                // 常量模式匹配
11                   break;
12               case short sval:       // 類型模式匹配
13                   sum += sval;
14                   break;
15               case int ival:
16                   sum += ival;
17                   break;
18               case string str when int.TryParse(str, out var result):   // 類型模式匹配 + 條件表達式
19                   sum += result;
20                   break;
21               case IEnumerable<object> subList when subList.Any():
22                   sum += GetSum(subList);
23                   break;
24               default:
25                   throw new InvalidOperationException("未知的類型");
26           }
27       }
28   
29       return sum;
30   }

?使用方法:

 1   switch (item)
 2   {
 3       case type variable1:
 4           // processing...
 5           break;
 6       case type variable2 when predicate:
 7           // processing...
 8           break;
 9       default:
10           // processing...
11           break;
12   }

?原理解析:此 switch 非彼 switch,編譯后你會發現擴展的 switch 就是 as 、if 、goto 語句的組合體。同 is?expressions 一樣,以前我們也能實

?現只是寫法比較繁瑣并且可讀性不強。

?總結:模式匹配語法是想讓我們在簡單的情況下實現類似與多態一樣的動態調用,即在運行時確定成員類型和調用具體的實現。

4. 局部引用和引用返回 (Ref locals and returns)

?我們知道 C# 的 ref 和 out 關鍵字是對值傳遞的一個補充,是為了防止值類型大對象在Copy過程中損失更多的性能。現在在C# 7中?ref 關鍵字得

?到了加強,它不僅可以獲取值類型的引用而且還可以獲取某個變量(引用類型)的局部引用。如:

 1   static ref int GetLocalRef(int[,] arr, Func<int, bool> func)
 2   {
 3       for (int i = 0; i < arr.GetLength(0); i++)
 4       {
 5           for (int j = 0; j < arr.GetLength(1); j++)
 6           {
 7               if (func(arr[i, j]))
 8               {
 9                   return ref arr[i, j];
10               }
11           }
12       }
13   
14       throw new InvalidOperationException("Not found");
15   }

?Call:

1   int[,] arr = { { 10, 15 }, { 20, 25 } };
2   ref var num = ref GetLocalRef(arr, c => c == 20);
3   num = 600;
4   
5   Console.WriteLine(arr[1, 0]);

?Print results:

?

?使用方法:

?1. 方法的返回值必須是引用返回:

? ? ?a) ?聲明方法簽名時必須在返回類型前加上 ref 修飾。

? ? ?b) ?在每個 return 關鍵字后也要加上 ref 修飾,以表明是返回引用。

?2. 分配引用(即賦值),必須在聲明局部變量前加上 ref 修飾,以及在方法返回引用前加上 ref 修飾。

?注:C# 開發的是托管代碼,所以一般不希望程序員去操作指針。并由上述可知在使用過程中需要大量的使用 ref 來標明這是引用變量(編譯后其

?實沒那么多),當然這也是為了提高代碼的可讀性。?

?總結:雖然 C# 7 中提供了局部引用和引用返回,但為了防止濫用所以也有諸多約束,如:

?1. 你不能將一個值分配給 ref 變量,如:

1   ref int num = 10;   // error:無法使用值初始化按引用變量

?2. 你不能返回一個生存期不超過方法作用域的變量引用,如:

1 public ref int GetLocalRef(int num) => ref num;   // error: 無法按引用返回參數,因為它不是 ref 或 out 參數

?3. ref 不能修飾 “屬性” 和 “索引器”。?

1   var list = new List<int>();
2   ref var n = ref list.Count;  // error: 屬性或索引器不能作為 out 或 ref 參數傳遞 

?原理解析:非常簡單就是指針傳遞,并且個人覺得此語法的使用場景非常有限,都是用來處理大對象的,目的是減少GC提高性能。

5.?局部函數(Local functions)

?C# 7 中的一個功能“局部函數”,如下所示:

 1    static IEnumerable<char> GetCharList(string str)
 2    {
 3        if (IsNullOrWhiteSpace(str))
 4            throw new ArgumentNullException(nameof(str));
 5    
 6        return GetList();
 7    
 8        IEnumerable<char> GetList()
 9        {
10            for (int i = 0; i < str.Length; i++)
11            {
12                yield return str[i];
13            }
14        }
15    }

?使用方法:

1   [數據類型,void] 方法名([參數])
2   {
3      // Method body;[] 里面都是可選項
4   }

?原理解析:局部函數雖然是在其他函數內部聲明,但它編譯后就是一個被 internal 修飾的靜態函數,它是屬于類,至于它為什么能夠使用上級函

?數中的局部變量和參數呢?那是因為編譯器會根據其使用的成員生成一個新類型(Class/Struct)然后將其傳入函數中。由上可知則局部函數的聲

?明跟位置無關,并可無限嵌套。

?總結:個人覺得局部函數是對 C# 異常機制在語義上的一次補充(如上例),以及為代碼提供清晰的結構而設置的語法。但局部函數也有其缺點,

?就是局部函數中的代碼無法復用(反射除外)。

6. 更多的表達式體成員(More expression-bodied members)

?C# 6 的時候就支持表達式體成員,但當時只支持“函數成員”和“只讀屬性”,這一特性在C# 7中得到了擴展,它能支持更多的成員:構造函

?、析構函數、帶 get,set 訪問器的屬性、以及索引器。如下所示:

 1   public class Student
 2   {
 3       private string _name;
 4   
 5       // Expression-bodied constructor
 6       public Student(string name) => _name = name;
 7   
 8       // Expression-bodied finalizer
 9       ~Student() => Console.WriteLine("Finalized!");
10   
11       // Expression-bodied get / set accessors.
12       public string Name
13       {
14           get => _name;
15           set => _name = value ?? "Mike";
16       }
17   
18       // Expression-bodied indexers
19       public string this[string name] => Convert.ToBase64String(Encoding.UTF8.GetBytes(name));
20   }

?備注:索引器其實在C# 6中就得到了支持,但其它三種在C# 6中未得到支持。

7. Throw 表達式(Throw expressions)?

?異常機制是C#的重要組成部分,但在以前并不是所有語句都可以拋出異常的,如:條件表達式(? :)、null合并運算符(??)、一些Lambda

?表達式。而使用 C# 7 您可在任意地方拋出異常。如:

 1   public class Student
 2   {
 3       private string _name = GetName() ?? throw new ArgumentNullException(nameof(GetName));
 4   
 5       private int _age;
 6   
 7       public int Age
 8       {
 9           get => _age;
10           set => _age = value <= 0 || value >= 130 ? throw new ArgumentException("參數不合法") : value;
11       }
12   
13       static string GetName() => null;
14   }

8. 擴展異步返回類型(Generalized async return types)?

?以前異步的返回類型必須是:Task、Task<T>、void,現在 C# 7 中新增了一種類型:ValueTask<T>,如下所示:

1   public async ValueTask<int> Func()
2   {
3       await Task.Delay(3000);
4       return 100;
5   }

?總結:ValueTask<T> 與 ValueTuple 非常相似,所以就不列舉: ValueTask<T> 與 Task 之間的異同了,但它們都是為了優化特定場景性能而

?新增的類型。

  使用 ValueTask<T> 則需要導入: Install - Package System.Threading.Tasks.Extensions

9. 數字文本語法的改進(Numeric literal syntax improvements)?

?C# 7 還包含兩個新特性:二進制文字、數字分隔符,如下所示:

1   var one = 0b0001;
2   var sixteen = 0b0001_0000;
3   
4   long salary = 1000_000_000;
5   decimal pi = 3.141_592_653_589m;

?注:二進制文本是以0b(零b)開頭,字母不區分大小寫;數字分隔符只有三個地方不能寫:開頭,結尾,小數點前后。

?總結:二進制文本,數字分隔符 可使常量值更具可讀性。

轉載于:https://www.cnblogs.com/VVStudy/p/6551300.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/283964.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283964.shtml
英文地址,請注明出處:http://en.pswp.cn/news/283964.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在 C# 中如何檢查參數是否為 null

前言前不久&#xff0c;微軟宣布從 C# 11 中移除參數空值檢查功能&#xff0c;該功能允許在方法開始執行之前&#xff0c;在參數名稱的末尾提供參數空值檢查&#xff08;!!操作符&#xff09;。那么&#xff0c;在 C# 中如何檢查參數是否為 null 呢&#xff1f;1. null這個可能…

什么是Maven快照(SNAPSHOT)

本文來說下Maven的SNAPSHOT版本有什么作用 文章目錄 問題解決 正式版本"abc-1.0"快照版本"abc-1.0-SNAPSHOT"本文小結問題 在使用maven進行依賴管理時&#xff0c;有的版本號后面會帶有"-SNAPSHOT"&#xff0c;有什么作用呢&#xff1f; <dep…

帶你剖析WebGis的世界奧秘----Geojson數據加載(高級)

前言&#xff1a;前兩周我帶你們分析了WebGis中關鍵步驟瓦片加載點擊事件&#xff08;具體的看前兩篇文章&#xff09;&#xff0c;下面呢&#xff0c;我帶大家來看看Geojson的加載及其點擊事件 Geojson數據解析 GeoJSON是一種對各種地理數據結構進行編碼的格式。GeoJSON對象可…

如果要存ip地址,用什么數據類型比較好

在看高性能MySQL第3版&#xff08;4.1.7節&#xff09;時&#xff0c;作者建議當存儲IPv4地址時&#xff0c;應該使用32位的無符號整數&#xff08;UNSIGNED INT&#xff09;來存儲IP地址&#xff0c;而不是使用字符串。但是沒有給出具體原因。為了搞清楚這個原因&#xff0c;查…

微軟 .NET Core 3.1 年底將結束支持,請升級到.NET 6

微軟近日宣布&#xff0c;將于 2022 年 12 月 13 日停止為 .NET Core 3.1 提供服務更新、安全修復和技術支持。.NET Core 是一個免費開源的、用于 Windows、Linux 和 macOS 操作系統的軟件框架。該項目主要由微軟員工通過 .NET 基金會開發&#xff0c;并在 MIT 許可下發布。202…

軟件團隊的模式選擇

軟件團隊的模式分為&#xff1a;主治醫生模式、明星模式、社區模式、業余劇團模式、秘密團隊、特工團隊、交響樂團模式、爵士樂模式、功能團隊模式和官僚模式。 經過小組的討論&#xff0c;我們決定選用交響樂團模式獲得功能團隊模式。 交響樂團模式的優點是種類多&#xff0c;…

Angular 2

1. Angular2 官網 https://angular.io/guide/quickstart Node.js 下載 https://nodejs.org/en/ 怎么在vs code中使用angualr2 https://code.visualstudio.com/docs/nodejs/angular-tutorial moment.js:(javacript日期處理庫) http://momentjs.cn/ 2. ng2-hightCharts https://…

「Docker入門指北」容器很難理解?帶你從頭到尾捋一遍

文章目錄 1. 初始虛擬化 &#x1f351; 虛擬化概念&#x1f351; 硬件虛擬化2. Docker容器 &#x1f351; Docker技術的誕生&#x1f351; 容器與虛擬化&#x1f351; 性能差別&#x1f351; Docker優勢 編排有序高效易遷移快速部署3. 容器生態系統 &#x1f351; 核心技術 容器…

微服務:事務管理

幾乎所有的信息管理系統都會涉及到事務&#xff0c;事務的目的是為了保證數據的一致性&#xff0c;這里說的一致性是數據庫狀態的一致性。說到數據庫狀態的一致性&#xff0c;相信大家都會想到 ACID &#xff1a;原子性&#xff08;Atomic&#xff09;&#xff1a;在一個事件的…

js - flex布局測試案例:完美居中

<span>I love flex layout!</span><style>body{display:flex;justify-content:center;align-items:center;font-size:3em;color:#00ffff;}</style>![enter image description here][1]<p>與自己為敵&#xff0c;</p><p>與自己為友&a…

操作數據庫(對戰小游戲)

創建數據庫 1 create database duizhan2 go3 use duizhan4 go5 create table duizhan6 (7 Code varchar(20) not null primary key,8 Name varchar(20) not null,9 Sex varchar(20) not null, 10 Blood int, 11 Attack int, 12 Defence int, 13 Mingzhong…

8-Python3從入門到實戰—基礎之數據類型(集合-Sets)

Python從入門到實戰系列——目錄 集合的定義 集合&#xff08;set&#xff09;和字典類似&#xff0c;也是一組key的集合&#xff0c;但不存儲value&#xff1b;由于key不能重復&#xff0c;所以&#xff0c;在set中&#xff0c;沒有重復的key。創建一個set&#xff0c;需要提供…

Redis的那些事:一文入門Redis的基礎操作

Redis是什么Redis&#xff0c;全稱是Remote Dictionary Service,翻譯過來就是&#xff0c;遠程字典服務。redis屬于nosql非關系型數據庫。Nosql常見的數據關系&#xff0c;基本上是以key-value鍵值對形式存在的。Key-value: 就像翻閱中文字典或者單詞字典&#xff0c;通過指定的…

10種提問型爆文標題句式 直接套用

如果你用1天的時間來寫篇好文章&#xff0c;那你花掉半天時間想一個好標題都不過分&#xff01; 你是不是覺得我有點言過其實了&#xff1f;沒關系&#xff0c;先來問你2個問題&#xff1a; 1、花了很長時間&#xff0c;寫了一篇很牛的賣貨推文&#xff0c;定稿后&#xff0c…

同域和不同域長啥樣

相同域http://www.jiangdou.com/http://www.jiangdou.com/maidou 不同域http://www.jiangdou.comhttp://bbs.jiangdou.comhttps://www.jiangdou.comhttp://www.jiangdou.com:8080轉載于:https://www.cnblogs.com/MaiJiangDou/p/6689133.html

2016 China Joy搶先看,文末有彩蛋!

這里只有你想不到的&#xff0c;沒有你看不到的。 2016 China Joy開幕在即&#xff0c;天氣成了最折磨各種媒體、展商和觀眾的小妖精&#xff0c;一會艷陽天&#xff0c;一會大暴雨&#xff0c;軒軒現在是這樣的&#xff01; 七月底的魔都&#xff0c;熱的那叫一個銷魂&#x…

JdbcTemplate+PageImpl實現多表分頁查詢

一、基礎實體  MappedSuperclass public abstract class AbsIdEntity implements Serializable {private static final long serialVersionUID 7988377299341530426L;public final static int IS_DELETE_YES 1;// 標記刪除public final static int IS_DELETE_NO 0;// 未刪除…

消息隊列選型手冊

前言 消息隊列中間件重要嗎&#xff1f;面試必問問題之一&#xff0c;你說重不重要。我有時會問同事&#xff0c;為啥你用 RabbitMQ&#xff0c;不用 Kafka&#xff0c;或者 RocketMQ 呢&#xff1f; 他給我的回答&#xff1a;“因為公司用的就是這個&#xff0c;大家都這么用…

Jenkins 持續集成國產嵌入式操作系統 RT-Thread 的CI

我們直接在Jenkins的鏡像基礎上進行集成RT-Thread 的編譯環境&#xff0c; 這樣直接使用Shell 命令 最直接了當&#xff0c; 通過 第三方docker等插件&#xff0c; 嘗試了計重方案&#xff0c; 沒有找到理想中的感覺&#xff0c; 如果其他人有想法可以告知一二。 我們有現成的鏡…

codevs原創抄襲題 5960 信使

題目描述 Description?戰爭時期&#xff0c;前線有n個哨所&#xff0c;每個哨所可能會與其他若干個哨所之間有通信聯系。信使負責在哨所之間傳遞信息&#xff0c;當然&#xff0c;這是要花費一定時間的&#xff08;以天為單位&#xff09;。指揮部設在第一個哨所。當指揮部下達…