利用SwitchExpression來進行switch流程程式碼判斷的優化
今天突發奇想,想要用SwitchExpression來優化傳統switch語法上的複雜度(其實是程式碼量啦!),經過一番的測試總算想出一些小技巧來使用,將其記錄在此供日後參考。
傳統上的switch使用情境如下,程式碼寫起來比較冗長一點,閱讀上倒是很容易閱讀:
var iIndex = 1;
var cUrl = string.Empty;
switch(iIndex)
{
case 2:
cUrl = "BraBra2...";
break;
default:
cUrl = "BraBra1...";
break;
}
CallUrl(cUrl);
想要用C# 8.0之後的 SwitchExpression 來替代卻發現他根本是為了function / method而設計,不支援一般變數的寫法。於是改個想法,既然是function / method,那不如我就調用Func<TResult>
Delegate來實作,也是一種不錯的變通方式。於是程式碼改了一下:
var iIndex = 1;
System.Func<string> cUrl = () => iIndex switch {
2 => "BraBra2...",
_ => "BraBra1...",
};
CallUrl(cUrl());
程式碼行數瞬間少了一倍,由12行變成6行超舒服的。另因為只是想要取出字串,因此可以再進一步把function delegate的寫法拿掉,程式碼如下:
var iIndex = 1;
var cUrl = iIndex switch {
2 => "BraBra2...",
_ => "BraBra1...",
};
CallUrl(cUrl);
如果要用在字串插補(string interpolation)的地方又可以少掉一個參數的宣告,更舒服了:
var iIndex = 1;
Console.WriteLine($@"這是一句 {(iIndex switch {
2 => "BraBra2...",
_ => "BraBra1...",
})} 的展示。");
同場加映:Switch Expression內部選擇器突破單行限制
Switch Expression目前有一個很無奈的事實,就是他的內部選擇器沒有辦法如同LINQ Lambda語法進行直接委派,進而達成多行的語法表述。然而透過一些彆扭詭異的技巧還是可以突破限制,達成多行程式碼表述的目的,以下是簡略程式碼。(純粹語法示範,不要太在意程式碼的意義)
public string _cNickName = string.Empty;
public string cState
{
get => _cNickName;
set => _cNickName = value switch
{
string x when x.Equals("John", System.StringComparison.CurrentCultureIgnoreCase) => "約翰先生",
string x when x.StartsWith("Marry", System.StringComparison.CurrentCultureIgnoreCase) => ((System.Func<string>)(() => {
//故意展示多行程式碼的撰寫方式
return x.Equals("MarryQueen", System.StringComparison.CurrentCultureIgnoreCase) ?
$"瑪莉皇后" :
$"瑪莉小姐({x})";
}))(),
_ => value,
};
}
透過上述語法,我們可以發現先宣告一個閉包語法,裡面撰寫多行的程式碼表述後,再將其轉型為System.Func<string>
後,再透過()括號來強制運行,由此來突破Switch Expression單行表述限制。
不知道日後的C#更高版本是否會原生支援,但以當前C# 9.0版來說,只能靠這樣繞路而行。
相關連結
- 在C#的SwitchExpression下使用模式比對(Pattern Matching)
- 利用SwitchExpression來進行switch流程程式碼判斷的優化
- 利用SwitchExpression取代if-else,並閃避逐行判斷的寫法
- 利用C#的switch case when語法來忽略字串大小寫
- C#的IS與AS運算子之撰寫方法
- C#的NULL運算演化:?.、??、??=、以及模式比對增強功能
- 遞迴模式比對
- C# 9.0 中的新增功能