有没有办法让 switch 使用 C# 8 switch 表达式返回字符串值?

Posted

技术标签:

【中文标题】有没有办法让 switch 使用 C# 8 switch 表达式返回字符串值?【英文标题】:Is there a way for switch to return a string value using C# 8 switch expressions? 【发布时间】:2020-03-18 18:39:18 【问题描述】:

我有这段代码,其中开关的每个部分都向ModeMessage2 返回一个值。是否可以使用新的 C# switch 表达式(或任何其他代码优化)来优化 switch 的工作方式?

switch (Settings.Mode)

    case MO.Learn:
        ModeMessage2 =
            "Use this mode when you are first learning the phrases and their meanings.";
        if (Settings.Cc == CC.H)
        
            Settings.Cc = CC.JLPT5;
            App.cardSetWithWordCount = null;
            App.DB.RemoveSelected();
        
        break;
    case MO.Practice:
        ModeMessage2 =
             "Use this mode to help you memorize the phrases and their meanings.";
        if (Settings.Cc == CC.H)
        
            Settings.Cc = CC.JLPT5;
            App.cardSetWithWordCount = null;
            App.DB.RemoveSelected();
        
        break;
    case MO.Quiz:
        if (Settings.Cc == CC.H)
        
            Settings.Cc = CC.JLPT5;
            App.cardSetWithWordCount = null;
            App.DB.RemoveSelected();
        
        App.DB.UpdSet(SET.Adp, false);
        ModeMessage2 =
            "Use this mode to run a self marked test.";
        break;

【问题讨论】:

开关没有返回值。您返回一个字符串,您需要在每个 case 语句中设置一个字符串变量。字符串变量将在“switch”语句之前定义。 【参考方案1】:

您的代码类似于以下代码,但如果设置 ModeMessage2 或其他属性有副作用,那么事情发生的顺序可能很重要,在这种情况下,这在技术上并不是 100% 等效的。

IList<MO> specialModes = new[]  MO.Learn, MO.Practice, MO.Quiz ;

if (specialModes.Contains(Settings.Mode) && Settings.Cc == CC.H) 
   Settings.Cc = CC.JLPT5;
   App.cardSetWithWordCount = null;
   App.DB.RemoveSelected();


ModeMessage2 = Settings.Mode switch 
   MO.Learn => "Use this mode when you are first learning the phrases and their meanings.",
   MO.Practice => "Use this mode to help you memorize the phrases and their meanings.",
   MO.Quiz => "Use this mode to run a self marked test.",
   _ => "Unknown mode value" // or throw
;

if (Settings.Mode == MO.Quiz)
   App.DB.UpdSet(SET.Adp, false);

【讨论】:

【参考方案2】:
var modeMessage2 = Settings.Mode switch

    MO.Learn => "Use this mode when you are first learning the phrases and their meanings.",
    MO.Practice => "Use this mode to help you memorize the phrases and their meanings.",
    MO.Quiz => "Use this mode to run a self marked test."


if (Settings.Cc == CC.H)

    Settings.Cc = CC.JLPT5;
    App.cardSetWithWordCount = null;
    App.DB.RemoveSelected();


if (Settings.Mode == MO.Quiz) 
    App.DB.UpdSet(SET.Adp, false);


【讨论】:

编译器会抱怨,因为这个子句并不详尽【参考方案3】:

你应该使用字典来做到这一点--

 Dictionary<TypeOf(Settings.Mode), string> map = new Dictionary<TypeOf(Settings.Mode), string>();

 map.Add(MO.Learn,"Use this mode when you are first learning the phrases and their meanings.");
 map.Add(MO.Practice,"Use this mode to help you memorize the phrases and their meanings.");
 map.Add(MO.Quiz,"Use this mode to run a self marked test.");


 ModeMessage2 = map[Settings.mode]);

这将比任何 switch 语句都快得多,并且更易于维护。

如果有意义,您也可以使用数组。


以下评论者请注意:我做出以下假设,在某些情况下可能是错误的,但在一般情况下并非如此。 1) 代码的编写方式是“分配”在代码的整个生命周期内只发生一次——在这种情况下,如果地图被多次使用,您可以获得节省,以便在 N 次之后分配成本消失到 0。 2) 我们不知道密钥的类型,假设它是一个字符串的 cmets 正在做出一个可能不正确的假设。即便如此,字符串的任何“快速”比较都使用哈希,这与字典用来提高速度的方法相同。 3) 众所周知,编程中最慢的事情就是分支。字典(或数组映射)允许您没有任何分支,只是对内存位置的计算。

【讨论】:

比直接比较快吗? “比任何 switch 语句快得多”?我认为对于三个值,字典会比开关慢很多。 This will be much faster than any switch statement。它不会。对于更大的集合,确保字典会更快(Log(N) vs N)。对于N = 3,不会有明显差异 分配字典并填充它实际上会使其变慢 请注意,switch 语句难以置信地针对字符串进行了很好的优化。它首先对少量字符串进行线性搜索,然后在程序集中嵌入哈希函数并使用哈希码进行树搜索,最后使用字典。

以上是关于有没有办法让 switch 使用 C# 8 switch 表达式返回字符串值?的主要内容,如果未能解决你的问题,请参考以下文章

c# 8 switch 表达式:没有找到 switch 表达式的最佳类型

C#和C++的区别

C# 8 switch 表达式:一次处理多个案例?

c# 8.0 switch 表达式返回类型和空值

c# 8.0 switch 表达式中的多个案例[重复]

带有 void 的 C# 8.0 switch 语句 [重复]