Swift是否有类似C#的Switch表达式(而不是Switch语句)?

5
希望从标题中可以清楚地看出,我不是在问Swift是否支持Switch语句。我特别想知道Swift是否支持类似于C#的Switch表达式。
差异微妙但很重要。Switch语句是一种根据特定情况将代码行分组的方法。然而,Switch表达式会根据特定情况返回一个值。
假设您有以下枚举类型...
enum SomeEnum {
    case a
    case b
    case c
}

现在假设您需要根据特定的开关语句计算/返回一些值。目前,在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/条件执行代码。(是的,您也可以将所有内容放在一个函数中,然后仅调用该函数,但这与此问题无关。)
C# Switch Expression
相比之下,以下是使用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'在变量后面。此外,在大括号内,各个case之间用逗号隔开。最后,每个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的case语句中赋值变量 - undefined
2个回答

9

编辑:

此功能现计划于Swift 5.9版本中发布,并在今年WWDC的What's New in Swift会议中简要介绍。


编辑:

自从回答这个问题以来,关于在语言中添加ifswitch表达式的动态已经有所进展,具体形式可以参考SE-0380:ifswitch表达式,该提案已于2022年1月20日被接受。实现代码可以在apple/swift#62178中查看,并且该PR包含了可下载的工具链,但该功能尚未在Swift的发布版本中正式推出。

一旦该功能正式推出并纳入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>)
  • 控制转移语句 (break, continue等)
  • 延迟语句
  • Do语句
  • 编译器控制语句 (#if ..., #error, #warning等)

这是目前与语言核心紧密相关的事物,所以改变它将不是一项小任务!因此,这个特性也是 Swift“常见拒绝更改”列表中控制流最重要的一项:

if/elseswitch作为表达式:概念上支持这些是有趣的,但许多通过其他方式在 Swift 中已经解决了这些问题。将它们作为表达式引入了相当大的权衡,并且总体来说,我们还没有找到一个明显优于迄今为止的设计。

尽管如此,这是论坛上定期出现的一个问题,并且已经进行了广泛讨论(例如If / else expressions,其中包含了对switch表达式的大量讨论)。这是许多人想要的东西,所以我建议你通过阅读论坛上的一些帖子来了解最新情况,以获取关于如何提出建设性建议的想法,如果你有兴趣的话!

我将您的回答标记为已采纳,特别是因为您分享了“常被拒绝的更改”列表,这是我之前没有见过的。非常有帮助!谢谢! - Mark A. Donohoe
2
我已经更新了这个答案,加入了来自SE-0380的信息。该提案昨天被接受,并将在语言中添加ifswitch表达式。我会尽力在未来记得时保持更新。 - Itai Ferber

2
是的,你可以在Swift 5.9和Xcode 15中使用它。
let value = 0
let name =
    switch value {
    case 0:
        "iOS"
    default:
        "Android"
    }

您还可以将if用作表达式。
let name1 =
    if value == 1 {
        "iOS"
    } else {
        "Android"
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接