Swift是否有像C#一样的Switch * 表达式 *(与Switch * 语句 * 相对)?

bvjveswy  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(135)

希望通过本文的标题,可以清楚地看出我不是在问Swift是否支持Switch语句,而是在问Swift是否支持Switch***表达式***,类似于C#所拥有的。
两者的区别很微妙,但却很重要。Switch语句是一种基于特定大小写对代码行进行分组的方法。而Switch表达式***则返回一个基于特定大小写的值。
假设您有以下枚举...

enum SomeEnum {
    case a
    case b
    case c
}

现在假设你需要基于特定的switch语句计算/返回某个值。目前,在Swift中你必须使用Switch语句来完成这件事...

let someEnumValue: SomeEnum = .a

let result: String

switch someEnumValue {
    case .binary:      result = "This is the 'A' type"
    case .octal:       result = "This is the 'B' type"
    case .hexadecimal: result = "This is the 'C' type"
}

print(result)
//prints 'This is the 'A' type'

如上图所示,在Swift中,你必须先声明let result: String,但 * 不 * 给予它赋值,然后在Switch * 语句 * 中赋值,这是因为Switch * 语句 * 不返回值,它只基于匹配的case/condition执行代码。(是的,你也可以把所有这些放在一个函数中,然后简单地调用它,但这与这个问题是分开的。)

C#开关表达式

与此相反,下面是如何用C#编写它,并使用Switch表达式...

var result = someEnum switch {
    SomeEnum.a => "This is the 'A' type",
    SomeEnum.b => "This is the 'B' type",
    SomeEnum.c => "This is the 'C' type"
}

Console.WriteLine(result)
//prints 'This is the 'A' type'

正如您在这里看到的,由于Switch表达式返回值,因此Switch表达式直接将值赋给result变量。
注意:与Switch语句中单词“switch”位于变量之前不同,在Switch表达式中,单词switch位于变量 * 之后 *。此外,在大括号中,各个大小写用逗号分隔。最后,每个大小写只能是一个生成值的表达式。除非先将它们 Package 在自己的函数中,否则不能运行复合语句。

带闭包的伪版本

我的一个同事提出了这个方法,它使用了一个就地闭包。它稍微好一点,但是仍然没有真正的Switch表达式那么简单...

let result = {
    switch someEnum {
        case .a: return "This is the 'A' type"
        case .b: return "This is the 'B' type"
        case .c: return "This is the 'C' type"
    }
}()

print(result)

所以我的问题很简单... Swift支持Switch表达式吗?如果不支持,让我们都向Swift.org推荐它,因为它让事情变得更容易/更简单!

l0oc07j2

l0oc07j21#

    • 编辑:**

自从回答了这个问题之后,已经有了将ifswitch表达式以SE-0380: if and switch expressions(即accepted on 2022-01-20)的形式添加到该语言的运动。可以在apple/swift#62178上查看该实现,PR包括一个可下载的工具链,但该特性尚未在Swift的发布版本中登陆。
我会尝试更新这个答案再次一旦该功能使它成为一个航运版本的斯威夫特。
最初的答案是为后代保留如下:

    • 原件:**

不幸的是,Swift没有switch表达式,只有switch语句。Swift语言语法目前支持以下表达式:

  • 对标识符的引用
  • 文字
  • 自我表达(self.<whatever>self[<whatever>]等)
  • 超类表达式(super.<whatever>super[<whatever>]等)
  • 关闭
  • 带括号的表达式(表达式,在括号中)
  • 元组
  • 隐式成员表达式(对 * 将 * 引用self的函数或变量的引用,但基于上下文,允许跳过引用self-例如,foo(123)self.foo(123)相对)
  • 通配符(_
  • 密钥路径、选择器和密钥路径字符串

请注意,控制流语句、do语句和其他语句不包括在此列表中-Swift只允许将这些语句作为完整语句。

  • 表达式
  • 声明
  • 循环语句
  • 分支语句(if/guard/switch
  • 带标签的语句(label: <some statement>
  • 控制转移语句(breakcontinue等)
  • 延迟语句
  • Do语句
  • 编译器控制语句(#if ...#error#warning等)

这是目前与语言核心紧密相连的东西,所以改变它将是一个不小的壮举!出于这个原因,这个特性也在控制流的Swift "通常拒绝的更改"列表的顶部:
if / else and switch as expressions:这些都是概念上有趣的支持,但通过将它们转换为表达式解决的许多问题在Swift中已经通过其他方式得到了解决。将它们转换为表达式会带来重大的权衡,总的来说,我们还没有找到一个明显优于我们目前所拥有的设计。
尽管如此,这是论坛上定期出现的问题,并已得到广泛讨论(例如If / else expressions,其中也包含了很多关于switch表达式的讨论)。这是很多人想要的东西,所以我建议通过阅读论坛上的一些帖子来了解事物的最新状态,以获得关于什么/如何建设性地提出建议的想法,如果你感兴趣的话!

相关问题