【问题标题】:Does Swift have a Switch *expression* (as opposed to a Switch *statement*) like C#?Swift 有像 C# 一样的 Switch *表达式*(相对于 Switch *语句*)吗?
【发布时间】:2023-01-22 00:54:20
【问题描述】:

希望通过这个标题,很明显我不是在问 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 中陈述,你必须在那里分配价值。这是因为一个开关陈述不返回值。它仅根据匹配的案例/条件执行代码。 (是的,您也可以将所有这些放在一个函数中并简单地调用它,但这与这个问题是分开的。)

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'

正如您在此处看到的,Switch 表达式直接将值赋给result 变量,因为 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)

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

【问题讨论】:

    标签: swift switch-statement switch-expression


    【解决方案1】:

    编辑:

    自从回答了这个问题,有拥有一直在以 SE-0380: if and switch expressions 的形式向语言添加 ifswitch 表达式,并于 2022 年 1 月 20 日被接受。该实现可在apple/swift#62178 查看,PR 包括一个可下载的工具链,但该功能尚未登陆 Swift 的发布版本。

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

    原始答案保留在下面供后代使用:


    原版的:

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

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

    请注意,控制流语句、do 语句等内容未包含在此列表中——Swift 只允许将它们作为完整语句。目前,statements can be composed of

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

    这是目前与语言核心密切相关的东西,因此改变它绝非易事!出于这个原因,这个特性也在控制流的 Swift "commonly rejected changes" 列表的列表的顶部:

    if/else and switch as expressions:这些是值得支持的概念上有趣的东西,但是通过将它们变成表达式解决的许多问题已经在 Swift 中以其他方式解决了。使它们成为表达式会带来重大的权衡,总的来说,我们还没有找到明显比我们目前所拥有的更好的设计。

    尽管如此,这仍然是论坛上定期出现的问题,并且已经被广泛讨论(例如If / else expressions,其中也包含很多关于switch表达式的讨论)。这是很多人想要的东西,所以如果您有兴趣,我建议您阅读论坛上的一些主题以了解关于什么/如何建设性提议的想法,以了解最新的状态!

    【讨论】:

    • 投票接受你的,特别是因为你分享了“通常被拒绝的更改”列表,我不记得以前见过。超级有帮助!谢谢!
    • 我已经使用来自 SE-0380 的信息更新了这个答案,该信息昨天被接受,并将在语言中添加 ifswitch 表达式。我记得以后会尽量保持最新状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2011-03-28
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多