<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      說說 C# 9 新特性的實際運用

      你一定會好奇:“老周,你去哪開飛機了?這么久沒寫博客了。”

      老周:“我買不起飛機,開了個鐵礦,挖了一年半的石頭。誰知鐵礦垮了,壓死了幾條蜈蚣,什么也沒挖著。”

      所以,這么丟死人的事,還是不要提了,爺爺從小教導我做人要低調……

       

      一轉眼,.NET 5 要來了,同時也帶來了 C# 9。遙想當年,老周剛接觸 .NET 1.1 的時候,才剛上大學;如今已經過去13年了。歲月是把水果刀,從來不饒人啊。

      老周很少去寫諸如“XXX新特性”之類的文章,總覺得沒啥用處。不過,針對 C# 9,老周想說一點什么。

      好,在開始之前,老周再次強調一下:這些語言新特性的東西,你千萬不要特意去學習,千萬不要,不要,不要,重要的事情講四遍!這些玩意兒你只要看看官方給的說明,刷一遍就能掌握了(刷這個比刷抖音有意義多了),不用去學的。如果你連這些東東也要學習成本的話,我只想說句好唱不好聽的話——你的學習能力真的值得懷疑

       

      好了,下面開始表演。

      第一出:record 類型

      record ,我還是用原詞吧,我知道有翻譯為“記錄類型”的說法。只是,只是,老周老覺得這不太好聽,可是老周也找不出更好的詞語,還是用回 record吧。

      record 是引用類型,跟 class 很像(確實差不多)。那么,用人民群眾都熟悉的 class 不香嗎,為何要新增個 record 呢?答:為了數據比較的便捷。

      不明白?沒事,往下看。最近有一位熱心鄰居送了老周一只寵物:

          public class Cat
          {
              public string Nick { get; set; }
              public string Name { get; set; }
              public int Age { get; set; }
          }

      這只新寵物可不簡單,一頂一的高級吃貨。魚肉、豬肉、雞腿、餅干、豆腐、面包、水果、面條、小麥、飛蛾……反正,只要它能塞進嘴里的,它都吃。

      接下來,我們 new 兩個寵物實例。

                  // 兩個實例描述的是同一只貓
                  Cat pet1 = new Cat
                  {
                      Nick = "松子",
                      Name = "Jack",
                      Age = 1
                  };
                  Cat pet2 = new Cat
                  {
                      Nick = "松子",
                      Name = "Jack",
                      Age = 1
                  };
      
                  // 居然不是同一只貓
                  Console.WriteLine("同一只?{0}", pet1 == pet2);

      其實,兩個實例描述的都是我家的乖乖。可是,輸出的是:

      同一只?False

      這是因為,在相等比較時,人家關心的類型引用——引用的是否為同一個實例。但是,在數據處理方案中,我們更關注對象中的字段/屬性是否相等,即內容比較。

      現在,把 Cat 的聲明改為 record 類型。

          public record Cat
          {
              public string Nick { get; set; }
              public string Name { get; set; }
              public int Age { get; set; }
          }

      然后同樣用上面的 pet1 和 pet2 實例進行相等比較,得到預期的結果:

      同一只?True

       

      record 類型讓你省去了重寫相等比較(重寫 Equals、GetHashCode 等方法或重載運算符)的邏輯。

      實際上,代碼在編譯后 record 類型也是一個類,但自動實現了成員相等比較的邏輯。以前你要手動去折騰的事現在全交給編譯器去干。

      假如,有一個 User 類型,用于表示用戶信息(包括用戶名、密碼),然后這個 User 類型在數據處理方案中可能會產生N多個實例。例如你根據條件從EF模型中篩選出一個 User 實例 A,根據用戶輸入的登錄名和密碼產生了 User 實例 B。為了驗證用戶輸入的登錄信息是否正確,如果 User 是 class,你可能要這樣判斷:

      if(A.UserName == B.UserName && A.Password == B.Password)
      {
          ..................
      }

      但要是你把 User 定義為 record 類型,那么,一句話的工夫:

      A == B

       

      第二出:模式匹配(Pattern Matching)

      "模式匹配"這個翻譯感覺怪怪滴,老周還沒想出什么更好的詞語。模式匹配并不是什么神奇的東西,它只是在對變量值進行檢測時的擴展行為。以前,老感覺C++/C# 的 switch 語句不夠強大,因為傳統的用法里面,每個 case 子句只能比較單個常量值。比如

                  int 考試成績 = 85;
      
                  switch (考試成績)
                  {
                      case 10:
                          Console.WriteLine("才考這么點破分啊");
                          break;
                      case 50:
                          Console.WriteLine("還差一點,就合格了");
                          break;
                      case 85:
                          Console.WriteLine("真是秀");
                          break;
                      case 90:
                          Console.WriteLine("奇跡發生");
                          break;
                  }

      我幻想著,要是能像下面這樣寫就好了:

                  switch (考試成績)
                  {
                      case 0:
                          Console.WriteLine("缺考?");
                          break;
                      case > 0 && <= 30:
                          Console.WriteLine("太爛了");
                          break;
                      case > 30 && < 60:
                          Console.WriteLine("還是不行");
                          break;
                      case >= 60 && < 80:
                          Console.WriteLine("還得努力");
                          break;
                      case >= 80 && < 90:
                          Console.WriteLine("秀兒,真優秀");
                          break;
                      case >= 90 && <= 100:
                          Console.WriteLine("不錯,奇跡");
                          break;
                  }

       

      等了很多年很多年(“千年等一回,等……”)以后,終于可以實現了。

                  switch (考試成績)
                  {
                      case 0:
                          Console.WriteLine("缺考?");
                          break;
                      case > 0 and <= 30:
                          Console.WriteLine("太爛了");
                          break;
                      case > 30 and < 60:
                          Console.WriteLine("還是不行");
                          break;
                      case >= 60 and < 80:
                          Console.WriteLine("還得努力");
                          break;
                      case >= 80 and < 90:
                          Console.WriteLine("秀兒,真優秀");
                          break;
                      case >= 90 and <= 100:
                          Console.WriteLine("不錯,奇跡");
                          break;
                  }

      喲西,真香。

       

      有時候,不僅要檢測對象的值,還得深入到其成員。比如下面這個例子,Order類表示一條訂單信息。

          public class Order
          {
              public int ID { get; set; }
              public string Company { get; set; }
              public string ContactName { get; set; }
              public float Qty { get; set; }
              public decimal UP { get; set; }
              public DateTime Date { get; set; }
          }

      前不久,公司接到一筆Order,做成了收益應該不錯。

                  Order od = new Order
                  {
                      ID = 11,
                      Company = "大嘴狗貿易有限公司",
                      ContactName = "陳大爺",
                      Qty = 425.12f,
                      UP = 1000.55M,
                      Date = new(2020, 10, 27)
                  };

      假如我要在變量 od 上做 switch,看看,就這樣:

                  switch (od)
                  {
                      case { Qty: > 1000f }:
                          Console.WriteLine("發財了,發財了");
                          break;
                      case { Qty: > 500f }:
                          Console.WriteLine("好家伙,年度大訂單");
                          break;
                      case { Qty: > 100f }:
                          Console.WriteLine("訂單量不錯");
                          break;
                  }

      咦?這,這是什么鬼?莫驚莫驚,這不是鬼。它的意思是判斷 Qty 屬性的值,如果訂單貨量大于 100 就輸出“訂單量不錯”;要是訂單貨量大于 1000,那就輸出“發財了,發財了”。

      但你會說,這對大括號怎么來的呢?還記得這種 LINQ 的寫法嗎?

          from x in ...
              where x.A ...
              select new {
                  Prop1 = ...,
                  Prop2 = ...,
                  ................
              }            

      new { ... } 是匿名類型實例,那如果是非匿名類型呢,看看前面的 Cat 實例初始化。

           Cat {
               ..........
           }

      這就對了,這對大括號就是構造某實例的成員值用的,所以,上面的 switch 語句其實是這樣寫的:

                  switch (od)
                  {
                      case Order{ Qty: > 1000f }:
                          Console.WriteLine("發財了,發財了");
                          break;
                      case Order{ Qty: > 500f }:
                          Console.WriteLine("好家伙,年度大訂單");
                          break;
                      case Order{ Qty: > 100f }:
                          Console.WriteLine("訂單量不錯");
                          break;
                  }

      Order{ ... } 就是匹配一個 Order 對象實例,并且它的 Qty 屬性要符合 ... 條件。由于變量 od 始終就是 Order 類型,所以,case 子句中的 Order 就省略了,變成

                      case { Qty: > 1000f }:
                          Console.WriteLine("發財了,發財了");
                          break;

      如果出現多個屬性,則表示為多個屬性設定匹配條件,它們之間是“且”的關系。比如

                      case { Qty: > 100f, Company: not null }:
                          Console.WriteLine("訂單量不錯");
                          break;

      猜猜啥意思?這個是可以“望文生義”的,Qty 屬性的值要大于 100,并且 Company 屬性的值不能為 null。不為 null 的寫法是 not null,不要寫成 !null,因為這樣太難看了。

       

      如果你的代碼分支較少,你可以用 if 語句的,只是得配合 is 運算符。

                  if (od is { UP: < 3000M })
                  {
                      Console.WriteLine("報價不理想");
                  }

      但是,這個寫法目前有局限性,它只能用常量值來做判斷,你要是這樣寫就會報錯。

                  if (od is { Date: < DateTime.Now })
                  {
                      ................
                  }

      DateTime.Now 不是常量值,上面代碼無法通過編譯。

       

      is 運算符以前是用來匹配類型的,上述的用法是它的語法擴展。

                  object n = 5000000L;
                  if(n is long)
                  {
                      Console.WriteLine("它是個長整型");
                  }

      進化之后的 is 運算符也可以這樣用:

                  object n = 5000000L;
                  if(n is long x)
                  {
                      Console.WriteLine("它是個長整型,存放的值是:{0}", x);
                  }

      如果你在 if 語句內要使用 n 的值,就可以順便轉為 long 類型并賦值給變量 x,這樣就一步到位,不必再去寫一句 long x = (long)n 。

       

      如果 switch... 語句在判斷之后需要返回一個值,還可以把它變成表達式來用。咱們把前面的 Order 例子改一下。

                  string message = od switch
                  {
                      { Qty: > 1000f }    => "發財了",
                      { Qty: > 500f }     => "年度大訂單",
                      { Qty: > 100f }     => "訂單量不錯",
                      _                   => "未知"
                  };
      
                  Console.WriteLine(message);

      這時候你得注意:

      1)switch 現在是表達式,不是語句塊,所以最后大括號右邊的分號不能少;

      2)因為 switch 成了表達式,就不能用 case 子句了,所以直接用具體的內容來匹配;

      3)最后返回“未知”的那個下劃線(_),也就是所謂的“棄嬰”,哦不,是“棄元”,就是雖然賦了值但不需要使用的變量,可以直接丟掉。這里就相當于 switch 語句塊中的 default 子句,當前面所有條件都不能匹配時,就返回“未知”。

       

      第三出:屬性的 init 訪問器

      要首先得知道,這個 init 只用于只讀屬性的初始化階段,對于可讀可寫的屬性,和以前一樣,直接 get; set; 即可。

      有人說這個 init 不知干啥用,那好,咱們先不說它,先來看看 C# 前些版本中新增的屬性初始化語句。

          public class Dog
          {
              public int No { get; } = 0;
              public string Name { get; } = "no name";
              public int Age { get; } = 1;
          }

      你看,這樣就可以給屬性分配初始值了,那還要 init 干嗎呢?

      好,我給你制造一個問題——我要是這樣初始化 Dog 類的屬性,你試試看。

                  Dog x = new Dog
                  {
                      No = 100,
                      Name = "吉吉",
                      Age = 4
                  };

      試一下,編譯會出錯吧。

       

       

      有些情況,你可以在屬性定義階段分配初始值,但有些時候,你必須要在代碼中初始化。在過去,我們會通過定義帶參數的構造函數來解決。

          public class Dog
          {
              public int No { get; } = 0;
              public string Name { get; } = "no name";
              public int Age { get; } = 1;
      
              public Dog(int no, string name, int age)
              {
                  No = no;
                  Name = name;
                  Age = age;
              }
          }

      然后,這樣初始化。

         Dog x = new(1001, "吉吉", 4);

       

      可是,這樣做的裝逼指數依然不夠高,你總不能每個類都來這一招吧,雖然不怎么辛苦,但每個類都得去寫一個構造函數,不利落。

      于是,init 訪問器用得上了,咱們把 Dog 類改改。

          public class Dog
          {
              public int No { get; init; }
              public string Name { get; init; }
              public int Age { get; init; }
          }

      你不用再去寫帶參數的構造函數了,實例化時直接為屬性賦值。

                  Dog x = new Dog
                  {
                      No = 100,
                      Name = "吉吉",
                      Age = 4
                  };

      這樣一來,這些只讀屬性都有默認的初始值了。

      當然,這個賦值只在初始化過程中有效,初始化之后你再想改屬性的值,沒門!

                  x.Name = "冬冬";  //錯誤
                  x.Age = 10;       //錯誤

       

      嗯,好了,以上就是老周對 C# 9 新特性用法的一些不成文的闡述。看完后你就別說難了。

       

      posted @ 2020-11-09 18:14  東邪獨孤  閱讀(18276)  評論(41)    收藏  舉報
      主站蜘蛛池模板: 久久被窝亚洲精品爽爽爽| 亚洲欧美日韩综合久久久| 亚洲av日韩av永久无码电影| 国产精品老熟女一区二区| 超碰人人超碰人人| 中文字幕在线国产精品| 日韩精品18禁一区二区| 美女无遮挡免费视频网站| 天天澡日日澡狠狠欧美老妇 | 东宁县| 国产亚洲精品黑人粗大精选| 午夜三级成人在线观看| 成人拍拍拍无遮挡免费视频 | 蜜臀av一区二区三区不卡| 亚洲色婷婷综合开心网| 国偷自产一区二区三区在线视频| 国产乱久久亚洲国产精品| 人妻少妇精品性色av蜜桃| 久久亚洲精精品中文字幕| 国产欧美日韩精品丝袜高跟鞋| 中文字幕人妻无码一区二区三区| 国产男女猛烈无遮挡免费视频| 亚洲av高清一区二区三| 色偷偷www.8888在线观看| 精品国产乱码久久久久APP下载| 国产精品自拍午夜福利| 明光市| 午夜精品区| 92国产福利午夜757小视频| 美女裸体黄网站18禁止免费下载| 91一区二区三区蜜桃臀| 2019香蕉在线观看直播视频| 国产精品自在自线免费观看| 四虎库影成人在线播放| 日韩精品一区二区三区中文无码| 国产日产精品系列| 性视频一区| 九九热免费在线播放视频| 亚洲精品美女久久久久9999| 天天综合亚洲色在线精品| 福利视频一区二区在线|