亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#9特性record 類型、模式匹配、init 屬性詳情

 更新時間:2021年09月07日 14:42:18   作者:東邪獨狐  
這篇文章主要介紹了C#的record 類型、模式匹配(Pattern Matching)、屬性的 init 訪問器三大特性,感興趣的小伙伴請參考下面文章內(nèi)容

C#的特性record 類型、模式匹配、init 屬性

一、record 類型

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

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

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

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


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

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

            // 兩個實例描述的是同一只貓
            Cat pet1 = new Cat
            {
                Nick = "松子",
                Name = "Jack",
                Age = 1
            };
            Cat pet2 = new Cat
            {
                Nick = "松子",
                Name = "Jack",
                Age = 1
            };

            // 居然不是同一只貓
            Console.WriteLine("同一只?{0}", pet1 == pet2);


其實,兩個實例描述的都是我家的乖乖??墒牵敵龅氖牵?/p>

同一只?False

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

現(xiàn)在,把 Cat 的聲明改為 record 類型。

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


然后同樣用上面的 pet1 和 pet2 實例進(jìn)行相等比較,得到預(yù)期的結(jié)果:

同一只?True

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

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

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

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


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

A == B

二、模式匹配(Pattern Matching)

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


          

  int 考試成績 = 85;

            switch (考試成績)
            {
                case 10:
                    Console.WriteLine("才考這么點破分啊");
                    break;
                case 50:
                    Console.WriteLine("還差一點,就合格了");
                    break;
                case 85:
                    Console.WriteLine("真是秀");
                    break;
                case 90:
                    Console.WriteLine("奇跡發(fā)生");
                    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("秀兒,真優(yōu)秀");
                    break;
                case >= 90 && <= 100:
                    Console.WriteLine("不錯,奇跡");
                    break;
            }

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

          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("秀兒,真優(yōu)秀");
                    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,做成了收益應(yīng)該不錯。

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

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

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

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

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

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

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

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


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

            switch (od)
            {
                case Order{ Qty: > 1000f }:
                    Console.WriteLine("發(fā)財了,發(fā)財了");
                    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("發(fā)財了,發(fā)財了");
                    break;


如果出現(xiàn)多個屬性,則表示為多個屬性設(shè)定匹配條件,它們之間是“且”的關(guān)系。比如

                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("它是個長整型");
            }


進(jìn)化之后的 is 運算符也可以這樣用:

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


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

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

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

            Console.WriteLine(message);

這時候你得注意:

  1. switch 現(xiàn)在是表達(dá)式,不是語句塊,所以最后大括號右邊的分號不能少;
  2. 因為 switch 成了表達(dá)式,就不能用 case 子句了,所以直接用具體的內(nèi)容來匹配;
  3. 最后返回“未知”的那個下劃線(_),也就是所謂的“棄嬰”,哦不,是“棄元”,就是雖然賦了值但不需要使用的變量,可以直接丟掉。這里就相當(dāng)于 switch 語句塊中的 default 子句,當(dāng)前面所有條件都不能匹配時,就返回“未知”。

三、屬性的 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
            };


試一下,編譯會出錯吧。

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

    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);


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

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

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


你不用再去寫帶參數(shù)的構(gòu)造函數(shù)了,實例化時直接為屬性賦值。

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


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

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

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

以上就是C#的record 類型、模式匹配、init 屬性詳情的詳細(xì)內(nèi)容,更多關(guān)于C#的record 類型、模式匹配、init 屬性的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#常用正則驗證函數(shù)示例

    C#常用正則驗證函數(shù)示例

    這篇文章主要介紹了C#常用正則驗證函數(shù),舉例分析了C#針對IP驗證、價格驗證及正整數(shù)驗證的相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • 在Form_Load里面調(diào)用Focus無效的解決方法

    在Form_Load里面調(diào)用Focus無效的解決方法

    在調(diào)用Form_Load的時候,F(xiàn)orm其實還沒有進(jìn)入展示階段,自然Focus()調(diào)用也就沒效果了。
    2013-02-02
  • C#使用BackgroundWorker控件

    C#使用BackgroundWorker控件

    這篇文章介紹了C#使用BackgroundWorker控件的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • 如何使用C#掃描并讀取圖片中的文字

    如何使用C#掃描并讀取圖片中的文字

    本文介紹如何通過C# 程序來掃描并讀取圖片中的文字,這里以創(chuàng)建一個.Net Core程序為例。下面是具體步驟,供參考。有此需求的朋友可以了解下
    2021-06-06
  • Winform窗口實現(xiàn)多顯示屏顯示的2種方法

    Winform窗口實現(xiàn)多顯示屏顯示的2種方法

    這篇文章主要介紹了Winform窗口實現(xiàn)多顯示屏顯示的2種方法,本文直接給出了實現(xiàn)代碼,并對其中的一些重要參數(shù)做了解釋,需要的朋友可以參考下
    2015-06-06
  • Unity實現(xiàn)車型識別的示例代碼

    Unity實現(xiàn)車型識別的示例代碼

    這篇文章主要介紹了在Unity中接入百度AI,實現(xiàn)檢測一張車輛圖片的具體車型。即對于輸入的一張圖片(可正常解碼,且長寬比適宜),輸出圖片的車輛品牌及型號。需要的可以參考一下
    2022-01-01
  • C#中的矩形數(shù)組(多維數(shù)組)和鋸齒數(shù)組的實現(xiàn)

    C#中的矩形數(shù)組(多維數(shù)組)和鋸齒數(shù)組的實現(xiàn)

    本文主要介紹了C#中的矩形數(shù)組(多維數(shù)組)和鋸齒數(shù)組的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 關(guān)于Flyweight模式應(yīng)用實踐的相關(guān)介紹

    關(guān)于Flyweight模式應(yīng)用實踐的相關(guān)介紹

    本篇文章,小編將為大家介紹Flyweight模式應(yīng)用實踐,有需要的朋友可以參考一下
    2013-04-04
  • C#讀取txt文件數(shù)據(jù)的方法實例

    C#讀取txt文件數(shù)據(jù)的方法實例

    讀取txt文本數(shù)據(jù)的內(nèi)容,是我們開發(fā)中經(jīng)常會遇到的一個功能,這篇文章主要給大家介紹了關(guān)于C#讀取txt文件數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2021-05-05
  • C#自定義序列化ISerializable的實現(xiàn)方法

    C#自定義序列化ISerializable的實現(xiàn)方法

    這篇文章主要介紹了C#自定義序列化ISerializable的實現(xiàn)方法,涉及C#序列化的操作技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04

最新評論