欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

巧用 C#模式匹配,和if-else語(yǔ)句“說(shuō)拜拜”

admin
2024年12月23日 18:50 本文熱度 197

一、if-else語(yǔ)句維護(hù)難題知多少

(一)破壞程序結(jié)構(gòu)

在日常編程過(guò)程中,我們常常會(huì)使用到 if-else語(yǔ)句,它確實(shí)能夠幫助我們實(shí)現(xiàn)各種條件判斷下的不同邏輯處理。然而,當(dāng)代碼中大量使用if-else語(yǔ)句時(shí),就會(huì)產(chǎn)生不少問(wèn)題,其中對(duì)程序結(jié)構(gòu)的破壞尤為明顯。

隨著業(yè)務(wù)邏輯的復(fù)雜,if-else語(yǔ)句可能會(huì)層層嵌套,就像下面這樣一段簡(jiǎn)單模擬的代碼示例:

if (condition1 == true)

{

    f1();

}

else if (condition2 == true)

{

    f2();

}

else if (condition3 == true)

{

    f3();

}

起初這段代碼用于判斷不同條件時(shí)執(zhí)行不同的代碼塊,看著還算清晰。可一旦測(cè)試時(shí)發(fā)現(xiàn)了新問(wèn)題,需要調(diào)整邏輯,比如當(dāng) condition1condition3同時(shí)滿(mǎn)足時(shí)應(yīng)該先執(zhí)行f4,代碼修改后可能就變成了如下模樣:

else if (condition1 == true)

{

    if (condition3 == true)

    {

        f4();

    }

    f1();

}

else if (condition2 == true)

{

    f2();

}

else if (condition3 == true || condition4 == true)

{

    f3();

}

這還僅僅是比較簡(jiǎn)單的邏輯調(diào)整,如果是更為復(fù)雜的業(yè)務(wù)場(chǎng)景,if-else的數(shù)量會(huì)遠(yuǎn)遠(yuǎn)多于上述示例。要是各種condition都是使用flag變量進(jìn)行標(biāo)記時(shí),代碼的可讀性將會(huì)變得極差,后續(xù)開(kāi)發(fā)人員去理解代碼意圖就如同在迷宮中找出口一樣困難。而且在維護(hù)這樣的代碼時(shí),每一次修改都需要小心翼翼地梳理邏輯,極易牽一發(fā)而動(dòng)全身,大大增加了開(kāi)發(fā)和后期維護(hù)的成本。所以說(shuō),if-else語(yǔ)句大量嵌套時(shí),會(huì)使代碼邏輯變得復(fù)雜,讓程序結(jié)構(gòu)混亂不堪,對(duì)代碼的整體質(zhì)量有著不容忽視的負(fù)面影響。

(二)引發(fā)效率問(wèn)題

除了對(duì)程序結(jié)構(gòu)有破壞作用之外,if-else語(yǔ)句在某些情況下還會(huì)引發(fā)效率問(wèn)題。這就不得不提到現(xiàn)代CPU架構(gòu)中的相關(guān)知識(shí)了,像CPU的流水線(xiàn)結(jié)構(gòu)以及分支預(yù)測(cè)機(jī)制都和if-else語(yǔ)句的效率表現(xiàn)息息相關(guān)。

在現(xiàn)代 CPU執(zhí)行代碼時(shí),常常采用流水線(xiàn)技術(shù),例如三級(jí)流水線(xiàn),它在執(zhí)行一條指令時(shí),會(huì)同時(shí)讀取后面的指令,并對(duì)其進(jìn)行譯碼(也就是讀取、譯碼、執(zhí)行這幾個(gè)步驟同時(shí)進(jìn)行),這種方式能大大提高執(zhí)行效率。但流水線(xiàn)技術(shù)并不是在所有時(shí)候都有效的,當(dāng)程序中執(zhí)行到像if-else這類(lèi)帶有跳轉(zhuǎn)結(jié)構(gòu)的語(yǔ)句時(shí),情況就有所不同了。因?yàn)樘D(zhuǎn)意味著后續(xù)部分代碼可能不會(huì)按順序執(zhí)行了,那提前讀取的那些指令也就沒(méi)了用處,所以CPU會(huì)丟棄流水線(xiàn)現(xiàn)有的結(jié)果,此時(shí)if語(yǔ)句相對(duì)于順序執(zhí)行的指令,就會(huì)產(chǎn)生幾個(gè)時(shí)鐘周期的差距。不過(guò)這并非if語(yǔ)句特有的問(wèn)題,像switchfor等帶跳轉(zhuǎn)結(jié)構(gòu)的語(yǔ)句都會(huì)如此。

而分支預(yù)測(cè)則是為了進(jìn)一步應(yīng)對(duì)跳轉(zhuǎn)語(yǔ)句對(duì)效率的影響而引入的技術(shù)。簡(jiǎn)單來(lái)講,分支預(yù)測(cè)就是 CPU猜測(cè)條件判斷會(huì)走哪一路,如果猜對(duì)了,就能避免流水線(xiàn)停頓造成的時(shí)間浪費(fèi),可要是猜錯(cuò)了,那么流水線(xiàn)中推測(cè)執(zhí)行的那些中間結(jié)果全部要放棄,得重新獲取正確的分支路線(xiàn)上的指令開(kāi)始執(zhí)行,這就導(dǎo)致了程序執(zhí)行的延遲。并且,在大量使用if語(yǔ)句的地方,這種由于分支預(yù)測(cè)錯(cuò)誤帶來(lái)的影響還會(huì)被放大,它有可能產(chǎn)生10 - 20個(gè)時(shí)鐘周期的影響。

例如,在處理排序數(shù)組和未排序數(shù)組時(shí)進(jìn)行對(duì)比,有這樣一段代碼:

int arraySize = 32768;

int[] data = new int[arraySize];

Random rnd = new Random(0);

for (int c = 0; c < arraySize; ++c)

{

    data[c] = rnd.nextInt() % 256;

}

//排序后,比沒(méi)有排序要快!!!!!!!!!

Arrays.sort(data);

long start = System.nanoTime();

long sum = 0;

for (int i = 0; i < 100000; ++i)

{

    for (int c = 0; c < arraySize; ++c)

    {

        if (data[c] >= 128)

        {

            sum += data[c];

        }

    }

}

System.out.println((System.nanoTime() - start) / 1000000000.0);

System.out.println("sum = " + sum);

運(yùn)行這段代碼會(huì)發(fā)現(xiàn),排序后的數(shù)組在執(zhí)行包含 if判斷的循環(huán)時(shí),速度比未排序數(shù)組快很多,原因就是排序后的數(shù)據(jù)對(duì)于分支預(yù)測(cè)來(lái)說(shuō)更有規(guī)律,分支預(yù)測(cè)器能更準(zhǔn)確地猜測(cè)分支走向,而未排序的隨機(jī)數(shù)據(jù)則容易讓分支預(yù)測(cè)器猜錯(cuò),進(jìn)而導(dǎo)致效率降低。雖然在部分場(chǎng)景下,if-else語(yǔ)句對(duì)效率的影響可以忽略不計(jì),但它確實(shí)是存在效率方面的弊端的,也是我們?cè)诰幊虄?yōu)化時(shí)需要考慮的一個(gè)因素。

二、C#模式匹配閃亮登場(chǎng) 

(一)類(lèi)型檢查和轉(zhuǎn)換優(yōu)勢(shì)

 C#編程中,我們常常會(huì)遇到需要檢查對(duì)象是否為特定類(lèi)型并且進(jìn)行轉(zhuǎn)換的情況。以往,我們可能會(huì)使用傳統(tǒng)的as is 操作符來(lái)完成這類(lèi)任務(wù)。例如,使用is 操作符判斷類(lèi)型后,再通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換來(lái)獲取對(duì)應(yīng)類(lèi)型的對(duì)象,像這樣:

object obj = "SomeString";

if (obj is string)

{

    string str = (string)obj;

    //后續(xù)對(duì)str進(jìn)行操作

}

或者使用as 操作符來(lái)嘗試轉(zhuǎn)換類(lèi)型:

object obj = "SomeString";

string str = obj as string;

if (str!= null)

{

    //對(duì)str進(jìn)行操作

}

可以看到,使用傳統(tǒng)方式在進(jìn)行類(lèi)型轉(zhuǎn)換后,還需要額外進(jìn)行null 檢查,以避免空引用異常的情況出現(xiàn),這樣就使得代碼變得相對(duì)繁瑣。

而模式匹配為我們提供了一種更為簡(jiǎn)潔的方式來(lái)完成類(lèi)型檢查和轉(zhuǎn)換任務(wù)。例如通過(guò)is 表達(dá)式結(jié)合聲明模式,我們可以在進(jìn)行類(lèi)型檢查的同時(shí)直接將結(jié)果賦值給變量,代碼如下:

object obj = "Hello";

if (obj is string str)

{

    Console.WriteLine(str);

}

在上述代碼中,當(dāng)obj 的運(yùn)行時(shí)類(lèi)型是string 時(shí),不僅完成了類(lèi)型檢查,還自動(dòng)將其賦值給了變量str,而且這個(gè)過(guò)程中隱含了對(duì)null 值的檢查。如果obj null,那么這個(gè)條件判斷就直接為false,不會(huì)進(jìn)入后續(xù)的代碼塊,有效避免了空引用問(wèn)題,使代碼更加精簡(jiǎn)、安全且易讀。

(二)簡(jiǎn)化復(fù)雜條件邏輯

當(dāng)業(yè)務(wù)邏輯變得復(fù)雜,涉及到多個(gè)條件和不同類(lèi)型的判斷時(shí),大量使用if-else 鏈或者傳統(tǒng)的switch 語(yǔ)句會(huì)讓代碼的可讀性變得很差。比如下面這樣一段模擬的傳統(tǒng)if-else 代碼:

if (obj is TypeA a)

{

    if (a.Property1 > 10)

    {

        //執(zhí)行操作1

    }

    else if (a.Property2 == "SomeValue")

    {

        //執(zhí)行操作2

    }

    else

    {

        //執(zhí)行操作3

    }

}

else if (obj is TypeB b)

{

    if (b.Field1 < 5)

    {

        //執(zhí)行操作4

    }

    else

    {

        //執(zhí)行操作5

    }

}

隨著條件的增多以及類(lèi)型的多樣化,這段代碼會(huì)越來(lái)越長(zhǎng),后續(xù)開(kāi)發(fā)人員去理解其中的邏輯就會(huì)變得十分困難。

而使用模式匹配的switch 語(yǔ)句或者switch 表達(dá)式,就能很好地簡(jiǎn)化這類(lèi)復(fù)雜邏輯。例如:

return obj switch

{

    TypeA a when a.Property1 > 10 => //執(zhí)行對(duì)應(yīng)操作1的代碼,

    TypeA a when a.Property2 == "SomeValue" => //執(zhí)行對(duì)應(yīng)操作2的代碼,

    TypeA _ => //執(zhí)行對(duì)應(yīng)操作3的代碼,

    TypeB b when b.Field1 < 5 => //執(zhí)行對(duì)應(yīng)操作4的代碼,

    TypeB _ => //執(zhí)行對(duì)應(yīng)操作5的代碼,

    _ => throw new ArgumentException("未知類(lèi)型")

};

通過(guò)模式匹配的switch,我們可以基于不同的類(lèi)型以及對(duì)應(yīng)類(lèi)型下的條件,清晰直觀地梳理出邏輯分支,把原本嵌套復(fù)雜的if-else 鏈轉(zhuǎn)換為簡(jiǎn)潔明了的結(jié)構(gòu),讓代碼的邏輯一目了然,更易于理解和維護(hù)。

(三)解構(gòu)復(fù)合類(lèi)型便捷性

在處理復(fù)合類(lèi)型(如元組、自定義類(lèi)等)時(shí),有時(shí)我們需要從中提取值來(lái)進(jìn)行后續(xù)的操作。以往的做法可能需要編寫(xiě)專(zhuān)門(mén)的解構(gòu)代碼,過(guò)程相對(duì)繁瑣。

例如對(duì)于一個(gè)包含姓名和年齡的Person 類(lèi):

class Person

{

    public string Name { get; set; }

    public int Age { get; set; }

}

如果不使用模式匹配,要提取其中的值可能是這樣的:

Person person = new Person { Name = "John", Age = 30 };

string name = person.Name;

int age = person.Age;

//然后使用nameage進(jìn)行后續(xù)操作

而借助模式匹配,我們可以直接在條件檢查中進(jìn)行解構(gòu)。比如:

Person person = new Person { Name = "John", Age = 30 };

if (person is { Name: string n, Age: int a })

{

    Console.WriteLine($"姓名是{n},年齡是{a}");

}

在上述代碼中,通過(guò)模式匹配的語(yǔ)法,在判斷person 對(duì)象是否符合條件的同時(shí),直接將其內(nèi)部的Name Age 屬性解構(gòu)賦值到了對(duì)應(yīng)的變量上,無(wú)需額外編寫(xiě)復(fù)雜的解構(gòu)代碼,使得代碼更加簡(jiǎn)潔,減少了不必要的代碼量,提升了代碼的整體可讀性。

(四)范圍檢查更輕松

在很多編程場(chǎng)景中,我們需要對(duì)某個(gè)數(shù)值進(jìn)行范圍檢查,判斷它是否落在特定的區(qū)間內(nèi)。在沒(méi)有模式匹配的情況下,我們可能會(huì)使用類(lèi)似下面這樣的if 語(yǔ)句來(lái)實(shí)現(xiàn):

int num = 80;

if (num >= 60 && num <= 100)

{

    Console.WriteLine("成績(jī)合格");

}

else if (num > 100)

{

    Console.WriteLine("成績(jī)優(yōu)秀");

}

else

{

    Console.WriteLine("成績(jī)不及格");

}

隨著范圍判斷條件的增多,代碼也會(huì)變得越來(lái)越復(fù)雜,可讀性逐漸變差。

不過(guò),C# 9.0引入的關(guān)系模式讓范圍檢查的代碼得到了極大簡(jiǎn)化。例如:

int num = 80;

if (num is >= 60 and <= 100)

{

    Console.WriteLine("成績(jī)合格");

}

else if (num is > 100)

{

    Console.WriteLine("成績(jī)優(yōu)秀");

}

else

{

    Console.WriteLine("成績(jī)不及格");

}

又或者像這樣:

int score = 75;

if (score is (<= 100 and > 80))

{

    Console.WriteLine("良好");

}

if (score is (<= 80 and > 60))

{

    Console.WriteLine("中等");

}

通過(guò)關(guān)系模式的語(yǔ)法,我們可以直接在條件表達(dá)式中清晰地表達(dá)出范圍檢查的邏輯,使得代碼簡(jiǎn)潔明了,一眼就能看出具體的范圍判斷情況,讓范圍檢查相關(guān)的代碼編寫(xiě)和維護(hù)都變得更加輕松。

(五)邏輯組合更靈活

在實(shí)際編程中,經(jīng)常會(huì)遇到需要對(duì)多個(gè)條件進(jìn)行邏輯組合的情況,比如檢查一個(gè)值是否滿(mǎn)足多個(gè)條件之一或者是否滿(mǎn)足全部條件等。如果使用傳統(tǒng)的if-else 語(yǔ)句來(lái)實(shí)現(xiàn),往往會(huì)導(dǎo)致復(fù)雜的邏輯嵌套,代碼可讀性很差。

例如,判斷一個(gè)數(shù)字是否滿(mǎn)足特定的多個(gè)條件時(shí),可能會(huì)寫(xiě)成這樣:

int number = 150;

if ((number > 100 && number < 200) || (number > 200 && number < 300 && number!= 250))

{

    Console.WriteLine("a100-200之間或者200-300之間并且不是250");

}

可以看到,隨著條件增多和邏輯復(fù)雜度的提升,這樣的代碼理解起來(lái)就比較困難了。

而使用模式匹配中的邏輯模式,我們可以直接在模式匹配表達(dá)式中運(yùn)用andor not 等邏輯運(yùn)算符來(lái)組合條件。代碼如下:

int number = 150;

if (number is (> 100 and < 200) or (> 200 and < 300 and not 250))

{

    Console.WriteLine("a100-200之間或者200-300之間并且不是250");

}

通過(guò)這種方式,邏輯組合變得更加清晰直觀,避免了復(fù)雜的邏輯嵌套,讓代碼結(jié)構(gòu)更簡(jiǎn)潔,后續(xù)開(kāi)發(fā)人員在閱讀和維護(hù)代碼時(shí)也能更容易理解其中的邏輯關(guān)系,提高了代碼的可維護(hù)性。

(六)數(shù)據(jù)驗(yàn)證更緊湊

在數(shù)據(jù)驗(yàn)證場(chǎng)景中,驗(yàn)證邏輯往往會(huì)涉及到多個(gè)方面,比如類(lèi)型檢查、值范圍檢查以及特定屬性值檢查等。要是用傳統(tǒng)的方式來(lái)實(shí)現(xiàn),代碼可能會(huì)分散在多個(gè)不同的語(yǔ)句塊中,顯得比較松散且不易維護(hù)。

例如,驗(yàn)證一個(gè)用戶(hù)輸入的數(shù)據(jù)是否符合要求,可能會(huì)有如下代碼:

object input = //獲取用戶(hù)輸入的數(shù)據(jù)

if (input is int)

{

    int num = (int)input;

    if (num >= 0 && num <= 100)

    {

        //進(jìn)一步驗(yàn)證其他屬性相關(guān)邏輯(假設(shè)存在)

        if (/*滿(mǎn)足其他屬性相關(guān)條件*/)

        {

            Console.WriteLine("數(shù)據(jù)驗(yàn)證通過(guò)");

        }

    }

}

else

{

    Console.WriteLine("輸入的數(shù)據(jù)類(lèi)型不符合要求");

}

而使用模式匹配,我們可以在單個(gè)表達(dá)式中完成所有這些檢查。比如:

object input = //獲取用戶(hù)輸入的數(shù)據(jù)

if (input is int num && num >= 0 && num <= 100 && /*滿(mǎn)足其他屬性相關(guān)條件*/)

{

    Console.WriteLine("數(shù)據(jù)驗(yàn)證通過(guò)");

}

else

{

    Console.WriteLine("數(shù)據(jù)驗(yàn)證失敗");

}

通過(guò)模式匹配,將多種類(lèi)型的驗(yàn)證條件整合到了一起,使得驗(yàn)證邏輯更加緊湊,代碼的結(jié)構(gòu)更加清晰,無(wú)論是修改驗(yàn)證規(guī)則還是排查驗(yàn)證相關(guān)的問(wèn)題,都變得更加方便快捷,有效提升了代碼的可維護(hù)性。

(七)多態(tài)行為處理更簡(jiǎn)單

在處理需要依據(jù)對(duì)象類(lèi)型執(zhí)行不同操作的多態(tài)行為時(shí),傳統(tǒng)的做法通常是使用虛方法或者接口實(shí)現(xiàn)來(lái)完成。例如定義一個(gè)抽象基類(lèi)Animal,然后不同的具體動(dòng)物類(lèi)(如DogCat 等)繼承它并實(shí)現(xiàn)各自的行為方法:

abstract class Animal

{

    public abstract void MakeSound();

}

class Dog : Animal

{

    public override void MakeSound()

    {

        Console.WriteLine("汪汪汪");

    }

}

class Cat : Animal

{

    public override void MakeSound()

    {

        Console.WriteLine("喵喵喵");

    }

}

當(dāng)需要根據(jù)不同的動(dòng)物對(duì)象執(zhí)行對(duì)應(yīng)的叫聲行為時(shí),可能會(huì)這樣調(diào)用:

Animal animal = new Dog();

animal.MakeSound();

animal = new Cat();

animal.MakeSound();

這種方式在類(lèi)層次結(jié)構(gòu)比較復(fù)雜或者需要頻繁擴(kuò)展修改行為時(shí),就需要對(duì)類(lèi)的繼承體系進(jìn)行相應(yīng)調(diào)整,操作起來(lái)相對(duì)麻煩。

而模式匹配提供了一種更靈活的替代方式。比如:

Animal animal = new Dog();

if (animal is Dog d)

{

    d.MakeSound();

}

else if (animal is Cat c)

{

    c.MakeSound();

}

甚至可以使用模式匹配的switch 表達(dá)式來(lái)簡(jiǎn)化:

Animal animal = new Dog();

animal switch

{

    Dog d => d.MakeSound(),

    Cat c => c.MakeSound(),

    _ => Console.WriteLine("未知?jiǎng)游镱?lèi)型")

};

這樣在不修改原有類(lèi)層次結(jié)構(gòu)的前提下,能夠更容易地?cái)U(kuò)展或修改不同類(lèi)型對(duì)象對(duì)應(yīng)的行為,代碼的靈活性和可維護(hù)性都得到了提升。

(八)替代訪(fǎng)問(wèn)者模式更簡(jiǎn)潔

在實(shí)現(xiàn)訪(fǎng)問(wèn)者設(shè)計(jì)模式時(shí),通常需要為每種類(lèi)型單獨(dú)創(chuàng)建訪(fǎng)問(wèn)者方法,當(dāng)對(duì)象結(jié)構(gòu)比較復(fù)雜,涉及的類(lèi)型眾多時(shí),代碼量會(huì)變得很大,邏輯也會(huì)比較分散。

例如,假設(shè)有一個(gè)圖形的對(duì)象結(jié)構(gòu),包含圓形、矩形等不同類(lèi)型圖形,使用傳統(tǒng)訪(fǎng)問(wèn)者模式實(shí)現(xiàn)計(jì)算面積功能,可能會(huì)有如下代碼結(jié)構(gòu)(簡(jiǎn)單示意):

abstract class Shape

{

    public abstract void Accept(IVisitor visitor);

}

class Circle : Shape

{

    public double Radius { get; set; }

    public override void Accept(IVisitor visitor)

    {

        visitor.Visit(this);

    }

}

class Rectangle : Shape

{

    public double Width { get; set; }

    public double Height { get; set; }

    public override void Accept(IVisitor visitor)

    {

        visitor.Visit(this);

    }

}

interface IVisitor

{

    void Visit(Circle circle);

    void Visit(Rectangle rectangle);

}

class AreaCalculator : IVisitor

{

    public double TotalArea { get; private set; }

    public void Visit(Circle circle)

    {

        TotalArea += Math.PI * circle.Radius * circle.Radius;

    }

    public void Visit(Rectangle rectangle)

    {

        TotalArea += rectangle.Width * rectangle.Height;

    }

}

使用時(shí):

List<Shape> shapes = new List<Shape> { new Circle { Radius = 5 }, new Rectangle { Width = 4, Height = 6 } };

AreaCalculator calculator = new AreaCalculator();

foreach (var shape in shapes)

{

    shape.Accept(calculator);

}

Console.WriteLine($"總面積為{calculator.TotalArea}");

而通過(guò)模式匹配,可以作為一種更簡(jiǎn)潔的替代方案。例如:

List<Shape> shapes = new List<Shape> { new Circle { Radius = 5 }, new Rectangle { Width = 4, Height = 6 } };

double totalArea = 0;

foreach (var shape in shapes)

{

    totalArea += shape switch

    {

        Circle c => Math.PI * c.Radius * c.Radius,

        Rectangle r => r.Width * r.Height,

        _ => 0

    };

}

Console.WriteLine($"總面積為{totalArea}");

通過(guò)模式匹配,我們可以直接在一處處理所有類(lèi)型情況,無(wú)需為每種類(lèi)型單獨(dú)創(chuàng)建訪(fǎng)問(wèn)者方法,大大簡(jiǎn)化了代碼結(jié)構(gòu),讓代碼更加緊湊、易讀,在處理復(fù)雜對(duì)象結(jié)構(gòu)的相關(guān)邏輯時(shí)優(yōu)勢(shì)明顯。

三、實(shí)戰(zhàn)!用 C#模式匹配告別if-else

(一)簡(jiǎn)單邏輯場(chǎng)景應(yīng)用

在實(shí)際編程中,有很多簡(jiǎn)單的條件判斷邏輯場(chǎng)景,原本使用if-else 語(yǔ)句實(shí)現(xiàn)的代碼,都可以通過(guò) C#模式匹配進(jìn)行替換,讓代碼更加簡(jiǎn)潔、易讀和易維護(hù)。

比如,我們有一個(gè)根據(jù)不同分?jǐn)?shù)等級(jí)輸出對(duì)應(yīng)評(píng)價(jià)的場(chǎng)景,使用if-else 語(yǔ)句來(lái)寫(xiě)可能是這樣的:

int score = 85;

string comment = "";

if (score >= 90)

{

    comment = "優(yōu)秀";

}

else if (score >= 80 && score < 90)

{

    comment = "良好";

}

else if (score >= 60 && score < 80)

{

    comment = "及格";

}

else

{

    comment = "不及格";

}

Console.WriteLine(comment);

可以看到,雖然這段代碼邏輯比較清晰,但隨著條件的增多或者后續(xù)調(diào)整邏輯,代碼可能會(huì)變得越來(lái)越長(zhǎng)且嵌套復(fù)雜。

現(xiàn)在我們使用 C#模式匹配的switch 表達(dá)式來(lái)改寫(xiě)這段代碼,如下所示:

int score = 85;

string comment = score switch

{

    >= 90 => "優(yōu)秀",

    >= 80 and < 90 => "良好",

    >= 60 and < 80 => "及格",

    _ => "不及格"

};

Console.WriteLine(comment);

通過(guò)這樣的改寫(xiě),代碼一下子變得簡(jiǎn)潔明了,各個(gè)分?jǐn)?shù)區(qū)間的判斷條件清晰直觀地展示在switch 表達(dá)式中,一眼就能看出邏輯關(guān)系。而且如果后續(xù)需要增加新的分?jǐn)?shù)等級(jí)判斷或者調(diào)整區(qū)間范圍,修改起來(lái)也很方便,只需要在switch 表達(dá)式中添加或修改對(duì)應(yīng)的分支即可,避免了if-else 語(yǔ)句層層嵌套帶來(lái)的代碼混亂問(wèn)題,極大地提升了代碼的可維護(hù)性。

再比如,判斷一個(gè)數(shù)字是奇數(shù)還是偶數(shù)的場(chǎng)景,用傳統(tǒng)if-else 寫(xiě)法是:

int num = 10;

string result = "";

if (num % 2 == 0)

{

    result = "偶數(shù)";

}

else

{

    result = "奇數(shù)";

}

Console.WriteLine(result);

使用模式匹配可以改寫(xiě)為:

int num = 10;

string result = num switch

{

    var n when n % 2 == 0 => "偶數(shù)",

    _ => "奇數(shù)"

};

Console.WriteLine(result);

同樣,改寫(xiě)后的代碼更加簡(jiǎn)潔,邏輯也更清晰,很容易理解和維護(hù)。所以在這種簡(jiǎn)單邏輯場(chǎng)景下,C#模式匹配就已經(jīng)展現(xiàn)出了它相較于if-else 語(yǔ)句的優(yōu)勢(shì),能幫助我們寫(xiě)出更優(yōu)質(zhì)的代碼。

(二)復(fù)雜邏輯場(chǎng)景應(yīng)用

接下來(lái)看一個(gè)相對(duì)復(fù)雜的業(yè)務(wù)邏輯案例,假設(shè)有一個(gè)電商系統(tǒng),根據(jù)不同的用戶(hù)角色(普通用戶(hù)、會(huì)員、管理員)以及不同的商品類(lèi)型(電子產(chǎn)品、日用品、書(shū)籍)來(lái)計(jì)算折扣價(jià)格。

如果使用傳統(tǒng)的if-else 語(yǔ)句來(lái)實(shí)現(xiàn),代碼可能會(huì)像下面這樣:

string userRole = "會(huì)員";

string productType = "電子產(chǎn)品";

double originalPrice = 1000;

double discountedPrice = 0;

if (userRole == "普通用戶(hù)")

{

    if (productType == "電子產(chǎn)品")

    {

        discountedPrice = originalPrice * 0.95;

    }

    else if (productType == "日用品")

    {

        discountedPrice = originalPrice * 0.98;

    }

    else if (productType == "書(shū)籍")

    {

        discountedPrice = originalPrice * 0.9;

    }

}

else if (userRole == "會(huì)員")

{

    if (productType == "電子產(chǎn)品")

    {

        discountedPrice = originalPrice * 0.85;

    }

    else if (productType == "日用品")

    {

        discountedPrice = originalPrice * 0.9;

    }

    else if (productType == "書(shū)籍")

    {

        discountedPrice = originalPrice * 0.8;

    }

}

else if (userRole == "管理員")

{

    if (productType == "電子產(chǎn)品")

    {

        discountedPrice = originalPrice * 0.7;

    }

    else if (productType == "日用品")

    {

        discountedPrice = originalPrice * 0.8;

    }

    else if (productType == "書(shū)籍")

    {

        discountedPrice = originalPrice * 0.75;

    }

}

Console.WriteLine($"折扣后的價(jià)格為:{discountedPrice}");

可以想象,隨著用戶(hù)角色和商品類(lèi)型的不斷增加,這段代碼會(huì)變得極其復(fù)雜,嵌套層級(jí)越來(lái)越深,可讀性極差,后續(xù)維護(hù)成本也會(huì)非常高。

現(xiàn)在我們使用 C#模式匹配的switch 表達(dá)式來(lái)重構(gòu)這段代碼,如下所示:

string userRole = "會(huì)員";

string productType = "電子產(chǎn)品";

double originalPrice = 1000;

double discountedPrice = (userRole, productType) switch

{

    ("普通用戶(hù)", "電子產(chǎn)品") => originalPrice * 0.95,

    ("普通用戶(hù)", "日用品") => originalPrice * 0.98,

    ("普通用戶(hù)", "書(shū)籍") => originalPrice * 0.9,

    ("會(huì)員", "電子產(chǎn)品") => originalPrice * 0.85,

    ("會(huì)員", "日用品") => originalPrice * 0.9,

    ("會(huì)員", "書(shū)籍") => originalPrice * 0.8,

    ("管理員", "電子產(chǎn)品") => originalPrice * 0.7,

    ("管理員", "日用品") => originalPrice * 0.8,

    ("管理員", "書(shū)籍") => originalPrice * 0.75,

    _ => originalPrice

};

Console.WriteLine($"折扣后的價(jià)格為:{discountedPrice}");

通過(guò)這樣的重構(gòu),原本繁雜的if-else 結(jié)構(gòu)被清晰的switch 表達(dá)式所替代,每個(gè)用戶(hù)角色和商品類(lèi)型對(duì)應(yīng)的折扣計(jì)算邏輯一目了然。即使后續(xù)需要添加新的用戶(hù)角色或者商品類(lèi)型以及對(duì)應(yīng)的折扣規(guī)則,也只需要在switch 表達(dá)式中添加相應(yīng)的分支即可,不會(huì)對(duì)現(xiàn)有的代碼結(jié)構(gòu)造成太大的影響,極大地提升了代碼的整體質(zhì)量和可維護(hù)性。

再舉一個(gè)涉及多種類(lèi)型判斷以及復(fù)雜條件組合的例子,假設(shè)有一個(gè)圖形繪制系統(tǒng),根據(jù)傳入的圖形對(duì)象(圓形、矩形、三角形)以及一些額外的屬性(比如圓形的半徑范圍、矩形的長(zhǎng)寬比例范圍、三角形的角度范圍等)來(lái)決定是否可以繪制該圖形。

用傳統(tǒng)if-else 語(yǔ)句可能寫(xiě)成這樣(這里簡(jiǎn)化示意部分邏輯判斷代碼):

object shape = new Circle { Radius = 5 };

bool canDraw = false;

if (shape is Circle c)

{

    if (c.Radius >= 3 && c.Radius <= 10)

    {

        canDraw = true;

    }

}

else if (shape is Rectangle r)

{

    if (r.Width / r.Height >= 0.5 && r.Width / r.Height <= 2)

    {

        canDraw = true;

    }

}

else if (shape is Triangle t)

{

    //假設(shè)這里有更復(fù)雜的角度等條件判斷

    if (/*滿(mǎn)足三角形相關(guān)復(fù)雜條件*/)

    {

        canDraw = true;

    }

}

Console.WriteLine($"是否可以繪制該圖形:{canDraw}");

當(dāng)圖形種類(lèi)增多以及每個(gè)圖形的判斷條件變得更復(fù)雜時(shí),這段代碼會(huì)變得難以維護(hù)。

使用 C#模式匹配來(lái)重構(gòu),代碼如下:

object shape = new Circle { Radius = 5 };

bool canDraw = shape switch

{

    Circle c when c.Radius >= 3 && c.Radius <= 10 => true,

    Rectangle r when r.Width / r.Height >= 0.5 && r.Width / r.Height <= 2 => true,

    Triangle t when /*滿(mǎn)足三角形相關(guān)復(fù)雜條件*/ => true,

    _ => false

};

Console.WriteLine($"是否可以繪制該圖形:{canDraw}");

通過(guò)模式匹配的switch 語(yǔ)句,我們可以基于不同的圖形類(lèi)型以及對(duì)應(yīng)類(lèi)型下的復(fù)雜條件,清晰地梳理出邏輯分支,把原本嵌套復(fù)雜的if-else 鏈轉(zhuǎn)換為簡(jiǎn)潔明了的結(jié)構(gòu),讓代碼的邏輯更加清晰直觀,易于理解和維護(hù),即使面對(duì)復(fù)雜的業(yè)務(wù)邏輯場(chǎng)景,也能輕松應(yīng)對(duì),告別繁雜的if-else 語(yǔ)句帶來(lái)的困擾。

四、總結(jié)與展望

(一)總結(jié)模式匹配優(yōu)勢(shì)

通過(guò)前文的諸多示例與講解,我們可以清晰地看到 C#模式匹配在告別難以維護(hù)的if-else語(yǔ)句方面展現(xiàn)出了諸多優(yōu)勢(shì)。

首先,在類(lèi)型檢查和轉(zhuǎn)換方面,模式匹配提供了更簡(jiǎn)潔的方式,避免了傳統(tǒng)的asis操作符使用后還需額外進(jìn)行null檢查的繁瑣,讓代碼更加精簡(jiǎn)、安全且易讀。

對(duì)于復(fù)雜條件邏輯,無(wú)論是涉及多個(gè)條件還是不同類(lèi)型的判斷,模式匹配的switch語(yǔ)句或者表達(dá)式都能將原本嵌套復(fù)雜的if-else鏈轉(zhuǎn)換為簡(jiǎn)潔明了的結(jié)構(gòu),極大提升了代碼的可讀性,使邏輯一目了然,便于后續(xù)開(kāi)發(fā)人員理解與維護(hù)。

在解構(gòu)復(fù)合類(lèi)型時(shí),借助模式匹配可以直接在條件檢查中進(jìn)行解構(gòu),無(wú)需編寫(xiě)專(zhuān)門(mén)的解構(gòu)代碼,減少了不必要的代碼量,進(jìn)一步增強(qiáng)了代碼整體的可讀性。

范圍檢查上,C# 9.0引入的關(guān)系模式讓相關(guān)代碼得到極大簡(jiǎn)化,能直接在條件表達(dá)式中清晰表達(dá)范圍檢查邏輯,輕松應(yīng)對(duì)各種范圍判斷場(chǎng)景。

邏輯組合方面,利用模式匹配中的邏輯模式,可運(yùn)用andornot等邏輯運(yùn)算符在表達(dá)式中靈活組合條件,避免復(fù)雜的邏輯嵌套,使代碼結(jié)構(gòu)更簡(jiǎn)潔,邏輯關(guān)系更易理解。

數(shù)據(jù)驗(yàn)證場(chǎng)景中,模式匹配能夠把多種類(lèi)型的驗(yàn)證條件整合到單個(gè)表達(dá)式內(nèi),讓驗(yàn)證邏輯更加緊湊,結(jié)構(gòu)更清晰,無(wú)論是修改驗(yàn)證規(guī)則還是排查驗(yàn)證問(wèn)題都更加方便快捷。

處理多態(tài)行為時(shí),模式匹配提供了更靈活的替代方式,無(wú)需對(duì)原有類(lèi)層次結(jié)構(gòu)大動(dòng)干戈就能輕松擴(kuò)展或修改不同類(lèi)型對(duì)象對(duì)應(yīng)的行為,提升了代碼的靈活性與可維護(hù)性。

而且在替代訪(fǎng)問(wèn)者模式時(shí),模式匹配可直接在一處處理所有類(lèi)型情況,無(wú)需為每種類(lèi)型單獨(dú)創(chuàng)建訪(fǎng)問(wèn)者方法,大大簡(jiǎn)化了代碼結(jié)構(gòu),在面對(duì)復(fù)雜對(duì)象結(jié)構(gòu)相關(guān)邏輯時(shí)優(yōu)勢(shì)顯著。

總之,C#模式匹配從多個(gè)維度提升了代碼的可讀性、可維護(hù)性,讓我們編寫(xiě)的代碼更加優(yōu)質(zhì)、高效,告別以往if-else語(yǔ)句帶來(lái)的種種困擾。

(二)展望未來(lái)應(yīng)用發(fā)展

隨著 C#語(yǔ)言的不斷發(fā)展,模式匹配的功能和應(yīng)用場(chǎng)景勢(shì)必會(huì)進(jìn)一步擴(kuò)展和深化。從過(guò)往的發(fā)展歷程來(lái)看,像C# 12中引入的let模式優(yōu)化了變量重用,高級(jí)遞歸模式為處理嵌套對(duì)象和復(fù)雜數(shù)據(jù)結(jié)構(gòu)提供了更多靈活性,這些新特性的出現(xiàn)不斷增強(qiáng)著模式匹配的能力。

在未來(lái),或許我們能看到模式匹配在更多復(fù)雜業(yè)務(wù)場(chǎng)景中大放異彩,例如在處理大規(guī)模分布式系統(tǒng)中的數(shù)據(jù)交互與邏輯判斷時(shí),模式匹配可以憑借其簡(jiǎn)潔且強(qiáng)大的邏輯表達(dá)能力,更高效地梳理業(yè)務(wù)邏輯,減少代碼的復(fù)雜度。又或者在與新興技術(shù)如人工智能、大數(shù)據(jù)結(jié)合的應(yīng)用開(kāi)發(fā)中,模式匹配能夠幫助開(kāi)發(fā)人員更便捷地處理各種復(fù)雜的數(shù)據(jù)類(lèi)型和條件判斷,加速開(kāi)發(fā)進(jìn)程。

同時(shí),相信它在提升代碼性能方面也會(huì)有更多的優(yōu)化空間,在保證代碼可讀性和可維護(hù)性的同時(shí),讓程序運(yùn)行得更加高效。而且,隨著社區(qū)的不斷壯大以及開(kāi)發(fā)人員對(duì)其探索的深入,會(huì)有更多創(chuàng)新性的使用方式被挖掘出來(lái),模式匹配也將成為 C#編程中更加不可或缺的利器。

在此,鼓勵(lì)各位讀者積極在實(shí)際開(kāi)發(fā)中運(yùn)用這一技術(shù),不斷積累經(jīng)驗(yàn),緊跟 C#語(yǔ)言發(fā)展的步伐,利用模式匹配為我們帶來(lái)更優(yōu)質(zhì)、更易于維護(hù)的代碼,讓開(kāi)發(fā)工作變得更加得心應(yīng)手。


該文章在 2024/12/24 10:30:21 編輯過(guò)
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶(hù)的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved