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

Mar*_*eIV 6 switch-statement swift switch-expression

希望通过这个标题,我显然不是在问 Swift 是否支持 Switch 语句。我特别询问 Swift 是否支持 Switch表达式,类似于 C# 所支持的。

差异很微妙,但很重要。Switch 语句是一种根据特定情况对代码行进行分组的方法。然而,Switch 表达式会根据特定情况返回一个值。

假设您有以下枚举...

enum SomeEnum {
    case a
    case b
    case c
}
Run Code Online (Sandbox Code Playgroud)

现在假设您需要根据特定的 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'
Run Code Online (Sandbox Code Playgroud)

正如你在上面看到的,在 Swift 中,你必须首先声明let result: String给它赋值,然后在 Switch语句中,你必须在那里赋值。这是因为 Switch语句不返回值。它仅根据匹配的情况/条件执行代码。(是的,您也可以将所有这些放入一个函数中并简单地调用它,但这与这个问题是分开的。)

C# 开关表达式

相比之下,以下是使用 Switch表达式在 C# 中编写它的方式...

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'
Run Code Online (Sandbox Code Playgroud)

result正如您在此处所看到的,由于 Switch 表达式返回一个值,因此 Switch 表达式直接为变量赋值。

值得注意的是:与 Switch 语句中单词“switch”位于变量之前不同,在 Switch 表达式中,单词 switch 位于变量之后。此外,在大括号内,各个案例以逗号分隔。最后,每个 case 只能是产生一个值的单个表达式。除非首先将复合语句包装在它们自己的函数中,否则无法运行复合语句。

带闭包的伪版本

我的一位同事提出了这种使用就地关闭的方法。它好一点,但仍然不像真正的 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)
Run Code Online (Sandbox Code Playgroud)

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

Ita*_*ber 9

编辑:

\n

此功能现已计划在 Swift 5.9 中发布,并在今年的Swift 新增功能中进行了简要介绍WWDC 的

\n
\n

编辑:

\n

自从回答这个问题以来,出现了以SE-0380: and statements形式向语言添加ifand表达式的运动,该形式于 2022-01-20 被接受。该实现可以在apple/swift#62178查看,并且 PR 包含一个可下载的工具链,但该功能尚未登陆 Swift 的发行版本。switchifswitch

\n

一旦该功能成为 Swift 的发布版本,我将尝试再次更新这个答案。

\n

为后代保留原始答案如下:

\n
\n

原来的:

\n

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

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

请注意,控制流语句、do语句等内容不包含在此列表中 \xe2\x80\x94 Swift 只允许将它们作为完整语句。目前,语句可以由以下组成

\n
    \n
  • 表达式
  • \n
  • 声明
  • \n
  • 循环语句
  • \n
  • 分支语句 ( if// guard)switch
  • \n
  • 标记语句 ( label: <some statement>)
  • \n
  • 控制转移语句(breakcontinue等)
  • \n
  • 推迟陈述
  • \n
  • 做陈述
  • \n
  • 编译器控制语句(#if ...#error#warning等)
  • \n
\n

这是目前与语言核心密切相关的东西,因此改变它将是一个不小的壮举!因此,此功能也位于 Swift控制流“通常拒绝的更改”列表的顶部:

\n
\n

if/elseswitchas 表达式:这些在概念上是值得支持的有趣的东西,但是通过将它们放入表达式来解决的许多问题已经在 Swift 中以其他方式解决了。让它们成为表达式会带来重大的权衡,总的来说,我们还没有找到明显比我们迄今为止的设计更好的设计。

\n
\n

尽管如此,这仍然是论坛上定期出现的内容,并且已被广泛讨论(例如If / else 表达式,其中也包含大量switch表达式的讨论)。这是很多人都想要的东西,所以如果您有兴趣,我建议您通过阅读论坛上的一些帖子来了解最新的情况,以了解如何提出建设性建议的想法!

\n

  • 我已经用 [SE-0380](https://github.com/apple/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md) 的信息更新了这个答案,该信息于昨天被接受并将在语言中添加“if”和“switch”表达式。我记得,将来会尽力保持最新状态。 (2认同)