C# 8 开关表达式

Posted

技术标签:

【中文标题】C# 8 开关表达式【英文标题】:C# 8 Switch Expression 【发布时间】:2020-12-16 14:29:59 【问题描述】:

我可以用 C#8 switch expression 替换此代码片段吗?

请注意,如果 ObjectType 是 Computer,ObjectClass 将包含“person”,因此排序很重要。

另外,这个问题是学术性的,我只对switch expression 感兴趣,而不是如何解决这个特定问题。

public List<string> ObjectClass  get; set; 
public ObjectType ObjectType 
    get 
        if (ObjectClass.Contains("group"))       return ObjectType.Group; 
        if (ObjectClass.Contains("computer"))    return ObjectType.Computer; 
        if (ObjectClass.Contains("person"))      return ObjectType.User; 
        return ObjectType.Unknown;
    

【问题讨论】:

这是一个开关 表达式 - 语句不返回任何内容,只有表达式返回。是的,你可以,但它不会更漂亮。您发布的操作也会多次搜索该列表,因此您应该寻找避免多次迭代的方法。您可能需要一个 LINQ 调用来返回这三个单词中的任何一个单词的第一次出现并将其映射到目标值。这只会导致一次迭代,使代码速度提高 300% ObjectType 是枚举吗?在这种情况下,您可以使用Enum.Parse&lt;ObjectType&gt;() 将找到的任何数据直接解析为ObjectType 正如@PanagiotisKanavos 所指出的,使用switch expression 会导致代码不美观。这是演示如何使用 switch expression: dotnetfiddle.net/W57TEO 重写你的 getter。在我看来,在这种情况下使用 switch expression 不是一个好方法,因为 1) 没有执行匹配的值; 2) 每个case branch 不包含匹配值。 @IliarTurdushev 谢谢。问题是学术性的。我早些时候阅读了有关新开关的信息,并想看看我是否可以让它在这里工作。如果您想转发,我会将其标记为答案。 the question is academic and I am only interested in the switch expression 那是一个非常糟糕的例子。这是使用switch表达式或switch语句更清晰的情况之一 【参考方案1】:

您可以将 LINQ 和 switch 结合使用以获得(半)高效版本:

public ObjectType type

    get => ObjectClass.Select(c => c switch  "group" => ObjectType.Group, "computer" => ObjectType.Computer, "person" => ObjectType.Person, _ => (ObjectType?)null)
                      .FirstOrDefault(t => t != null) ?? ObjectType.Unknown;

【讨论】:

没有理由切换,同样可以使用不区分大小写的Enum.TryParse @PanagiotisKanavos 没错,但这个问题是专门关于使用 C# 8.0 switch 表达式的。 这根本没有必要,这个答案证明了这一点。这个例子根本不好。顺便说一句,if 语句的排序方式,group 优先于 computer 等。FirstOrDefault 还不够,您还需要订购它们。如果值来自枚举,这可以像OrderBy(x=&gt;x) 一样简单 @PanagiotisKanavos 它们是这样排序的,因为在 AD 中,所有 computer 帐户也是 person 帐户(因此,.Net 查询中存在一个错误,例如子类)所以你必须首先检查computer【参考方案2】:

这个答案建立在@IliarTurdushev 提供的解决方案之上,应该归功于他。还根据@NetMage 的建议进行了重构,谢谢。

public class Program

    public  List<string> ObjectClass  get; set; 
    public  ObjectType sample
    
        get => ObjectClass switch 
            _ when ObjectClass.Contains("group") => ObjectType.Group,
            _ when ObjectClass.Contains("computer") => ObjectType.Computer,
            _ when ObjectClass.Contains("person") => ObjectType.Person,
            _ => ObjectType.Unknown;
    

    public enum ObjectType
    
        Group = 1,
        Computer = 2,
        Person = 3,
        Unknown = 4
    

【讨论】:

这并不比原始代码好 - 它扫描列表 3 次 但回答了 Bob 提出的问题。请注意他说,“另外,这个问题是学术性的,我只对 switch 表达式感兴趣,而不是如何解决这个特定问题。” 这里的答案是“不要那样做”。这实际上被 F# 的人用作 反例 来展示 C# 的模式匹配是多么有限 那么欢迎您对原始问题投反对票。谢谢,祝您有美好的一天! 我建议使用get =&gt; ObjectClass switch... 而不是一个完整的正文——这就是使用表达式的意义。

以上是关于C# 8 开关表达式的主要内容,如果未能解决你的问题,请参考以下文章

void 方法的 C# 8 开关表达式

c# 8 switch 表达式不够“聪明”

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

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

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

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