利用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版來說,只能靠這樣繞路而行。

相關連結

  1. 在C#的SwitchExpression下使用模式比對(Pattern Matching)
  2. 利用SwitchExpression來進行switch流程程式碼判斷的優化
  3. 利用SwitchExpression取代if-else,並閃避逐行判斷的寫法
  4. 利用C#的switch case when語法來忽略字串大小寫
  5. C#的IS與AS運算子之撰寫方法
  6. C#的NULL運算演化:?.、??、??=、以及模式比對增強功能
  7. 遞迴模式比對
  8. C# 9.0 中的新增功能
C#8.0 C#9.0 SwitchExpression RecursivePatterns PatternMatching FuncDelegate ActionDelegate