稍加改進的Switch Case擴充套件方法

2021-09-05 21:53:16 字數 3543 閱讀 6218

先看一下他原文中的範例:

我覺得這裡唯一不爽的就是高亮的那部分,因為這裡必需要顯式宣告型別並作後續處理,我希望直接讓編譯器推導出返回型別,來看看改進後的實現:

string

typename = typeid.switch()

.casereturn(0, "

食品")

.casereturn(1, "

飲料")

.casereturn(2, "

酒水")

.casereturn(3, "

毒藥")

.defaultreturn("

未知")

.returnvalue;

在一連串的casereturn/defaultreturn後通過returnvalue屬性就可以訪問到最終的返回結果,這樣就可以直接使用,不需再傳入表示式進行後續處理了。

這樣做還有乙個好處,就是當**段位於方法體中時,可以直接return結果,而如果像原文那樣傳入表示式來處理結果的話,是不能直接return的,在表示式裡return僅會被視為表示式級別的return。

還有就是這樣的**段可以放在方法的引數中使用,這會很方便,可以將其視作三元表示式的加強版。

在原文中還有這樣一種過載:

看高亮部分,這個位置的引數只是用來對判斷依據進行調整,我覺得完全沒有必要,寫成password.length.switch(……)就行了呀,所以我沒有依照此過載方式實現。

以我的實現方式書寫的等效**為:

private

static

color getbackcolor2(string password)

雖然不傳入操作結果處理表示式就能安享編譯器的自動推導功能,但是有時操作結果表示式還是十分有用的,比如原文中的這個範例:

這裡首先讓所有篩選過程都禁用了break,然後通過傳入的表示式將依次返回的結果相累加。

對於這種應用來說,就必須傳入自定義的表示式來對結果進行處理了,也就必須要顯式宣告型別了,我對此的實現也與之相仿,但是我要求傳入的表示式具有兩個引數,第乙個引數是新獲得的返回結果,第二個引數是目前的返回結果,並要求該表示式返回經過處理後的結果,以代入下一次處理或用作最終結果,等效**為:

private

static

int getreward(int count)

有人可能奇怪,為什麼方法名都是casereturn、defaultreturn這樣的帶個return呢?這不是很囉嗦嘛?直接以case命名不好嗎?

這是因為我還實現了另一種形式:無返回值形式

參看下面的**:

private

void form1_formclosing(object sender, formclosingeventargs e) )

.defaultrun(f => e.cancel =

true); }

這段**通過caserun、defaultrun方法執行傳入的表示式,其功能就是根據不同對話方塊選項進行不同的處理,很容易理解。

之所以將caserun與casereturn區別命名,而不是過載,是因為casereturn也有類似於caserun的過載,即第二個引數也是表示式的過載。

雖然casereturn的過載中要求傳入的表示式要有返回值(func),而caserun的第二個引數不要求返回值(action),但是在傳入單句的lambda表示式的時候容易產生歧義。

比如表示式中執行了乙個帶有返回值的方法,由於單句lambda表示式不需顯式使用return關鍵字,所以編譯器就不能確切推導出要執行的是哪乙個過載,這樣編譯器就可能會抓狂,然後其視為最吻合的func形式過載,而編寫者可能僅僅是想執行一下該方法,並不希望獲取返回值並反映到結果中去。

(情景範例:在單句lambda表示式中呼叫了對資料庫執行sql語句的方法,該方法會返回受影響的記錄總數,而程式設計師可能是希望僅僅執行一下sql語句就好了,但恰巧此switch()方法鏈的返回結果被推導為int型別,程式就將此表示式匹配到func形式過載,就這樣糊里糊塗地讓這個返回值影響到了最終的返回結果)

所以如果不區別命名的話,在第二個引數中通過單句lambda表示式執行帶有返回值的方法時,程式就會傾向按照func的形式來執行,如是這樣的話,出現問題的可能性不大,但一旦趕巧出現歧義判定問題,就很煩人,而且很難查出來,故此我要保留這種區別命名的形式。

在使用中,以上展示的各種方法及其過載都可以混搭使用,但需注意以下幾點:

由於這個switch擴充套件方案支援傳入表示式做判定和執行,所以它還完全可以用於替代if……else if……else語句,比如下面**中,底部的那段**與注釋掉的那段**就是等價的:

varstr =

"test";

varon=true;

varday =

datetime

.today;

//if (str.startswith("t") && on) str = "1";

//else if (str.length > 9) str = "2";

//else if (str == "none")

//else if (day < datetime.now) str = "4";

//else on = false;

str.switch()

.caserun(f => f.startswith("t") && on, f => str =

"1")

.caserun(f => f.length >

9, f => str =

"2")

.caserun("none", f => )

.caserun(f => day <

datetime

.now, f => str =

"4")

.defaultrun(f => on =

false);

這樣的擴充套件除了讓**顯得更複雜以襯托出作者之牛b深奧之外,還有什麼優點?

優點就是能在單句lambda表示式中使用,這樣就能讓你更深奧一層……

哈哈,玩笑,不只是單句lambda表示式,在充當方法的引數時,三元表示式又不夠用的情況下,這樣的擴充套件就大有用武之地了,你可以不必大費周章地再去定義臨時的變數並給它賦值,或者專門建立乙個方法來解決這類簡單的判別問題。

它的形式可能不算優雅,但它能夠讓你的**結構變得優雅一些,並讓你專注於解決手頭的問題,而不是在**頁中上翻下抄瞎忙活。

再次感謝鶴沖天給我們帶來了那麼多的啟示,讓我們一同將擴充套件方法發揮到淋漓盡致吧,這是我們自製的語法糖啊:)

擴充套件方法源**:

本文的xps版本:

switch case 語句的用法

public class test7 結果是 five three other switch 表示式 switch的用法是判斷case後面的表示式和switch後面的表示式是否相匹配,一旦case匹配,就會順序執行後面的程式 而不管後面的case是否匹配,直到遇見break。如上所給的 中,由於i等...

簡單的switch case語句

簡單的switch case語句示例 public static void main string args else system.out.println 投幣不足請繼續投幣 int q 0 q m m if m 0 break case 2 else system.out.println 投幣不...

switch case 語句的用法

switch case 語句的用法 public class test7 結果是 five three other switch 表示式 switch的用法是判斷case後面的表示式和switch後面的表示式是否相匹配,一旦case匹配,就會順序執行後面的程式 而不管後面的case是否匹配,直到遇見...