先看一下他原文中的範例:
我覺得這裡唯一不爽的就是高亮的那部分,因為這裡必需要顯式宣告型別並作後續處理,我希望直接讓編譯器推導出返回型別,來看看改進後的實現:
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是否匹配,直到遇見...