簡體   English   中英

C# 8 用於 void 方法的開關表達式

[英]C# 8 switch expression for void methods

我知道用於返回值或屬性匹配的方法的C# 8 switch expression語法。 但是如果我們只需要打開一個字符串值並執行一個不返回任何內容(無返回類型/void)的方法,那么我們如何處理它呢? 我正在考慮某種形式的 Func 但不確定確切的語法。 我知道我們可以用常規的 case 語句用舊的方式來做,但試圖看看我們是否可以用新的語法來實現同樣的效果。

這是問題的示例

switch (stringvalue)
{
    case "Add": Add(); break;
    case "Subtract": Subtract(); break;
}

可能像:

stringvalue switch
{
    "Add" => Add(),
    "Subtract" => Subtract()
}
// but this complains that there needs to be assignment on left side for this

這可能嗎?

TL;博士

這不可能。 C# 8 switch expression不能返回void 它必須返回一個值,並且必須使用該值(分配給變量,作為參數傳遞給方法,作為方法的結果返回等)。 但是有一個解決方法。 我們可以編寫一個switch expression ,它返回一個delegate (例如Action類型),然后立即調用它:

(stringValue switch
 {
    "Add" => (Action) Add,
    "Subtract" => Subtract,
    _ => throw new ArgumentOutOfRangeException()
 })();

這種方法也可以與expression bodied methods一起使用。 這是演示


解釋

這可能嗎?

C# 8中這是不可能的。 C# specification中描述了此限制。

讓我們參考C# specification 從頁面Recursive Pattern Matching - Switch ExpressionStatements我們可以了解到:

  • switch_expression不允許作為expression_statement

  • 一個expression_statement計算一個給定的表達式。 表達式計算的值(如果有)將被丟棄。

從這兩個語句我們可以得出結論, switch_expression不能在expression_statement的上下文中使用,它的結果值也不能被丟棄。 必須使用結果值,例如,它必須分配給變量、作為參數傳遞給方法或作為方法的結果返回。 因此編譯器抱怨switch expression不能用作語句。


如果我們只需要打開一個字符串值並執行一個不返回任何內容(無返回類型/void)的方法,那么我們如何 go? 我正在考慮某種形式的 Func 但不確定確切的語法。

我們可以使用下一種方法:編寫一個switch expression ,它返回一個delegate ,然后立即調用它。 例如:

(stringValue switch
 {
    "Add" => (Action) Add,
    "Subtract" => Subtract,
    _ => throw new ArgumentOutOfRangeException()
 })();

此方法也可用於聲明expression bodied members

private static void Demo(string str) =>
    (str switch
     {
         "Add" => (Action) Add,
         "Subtract" => Subtract,
         _ => throw new ArgumentOutOfRangeException()
     })();

這是完整的示例

在我看來,這種解決方法看起來很丑陋,我個人更喜歡使用switch-caseif-else而不是這種結構。


可能在C#的未來版本中此限制將放寬( 請參閱此鏈接):

switch_expression不允許作為expression_statement

我們正在考慮在未來的修訂中放寬這一點。

但是我在csharplang repo中沒有找到合適的建議。

正如伊利亞爾告訴你的那樣,這是不可能的。 我有時使用的一種解決方法是添加一個始終返回 true 的本地 function,並且我在開關分配中使用了一個丟棄字符。 我發現這個解決方法比使用代表的方法更清晰一些。

例如,您可以在切換之前將此添加到您的代碼中:

bool Add() { [HEREYOURCODEToAdd]; return true;}
bool Substract() { [HEREYOURCODETOSubstract]; return true;}

然后你會這樣稱呼它:

_ = stringvalue switch {
    "Add" => Add(),
    "Substract" => Substract(),
};

我認為這種方法有一些用例。 例如,如果你想在 switch 中使用元組模式,它會比許多 annidated ifs 更具可讀性。 這是我正在使用的代碼,我認為這種方法比 ifs 更好:

           bool agregar(int índiceInicial, int índiceFinal) { visitasJson.Add(json[índiceInicial..índiceFinal]); return true; };
            _ = (índiceInicial, índiceFinal) switch {
                (0, -1) => agregar(índiceInicial + 1, índiceFinal - 3),
                (_, -1) => agregar(índiceInicial, índiceFinal - 1),
                (0, _) => agregar(índiceInicial + 5, índiceFinal),
                (_, _) => agregar(índiceInicial, índiceFinal),
            };

你真的想在你的用例中使用 switch 表達式嗎,傳統的方式要好得多。

所有建議的解決方案(如代表、丟棄)都是解決方法。

您試圖錯誤地使用 switch 表達式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM