如何与合并运算符一起使用try?

Jos*_*oid 5 swift

我正在尝试x从一个带有f一个参数(字符串)并抛出的函数分配一个值。

当前范围抛出了,所以我相信do... catch不是必需的。

我正在尝试try与合并运算符一起使用,??但出现此错误:'try' cannot appear to the right of a non-assignment operator

guard let x = try f("a") ??
              try f("b") ??
              try f("c") else {
    print("Couldn't get a valid value for x")
    return
}
Run Code Online (Sandbox Code Playgroud)

如果我更改trytry?

guard let x = try? f("a") ??
              try? f("b") ??
              try? f("c") else {
    print("Couldn't get a valid value for x")
    return
}
Run Code Online (Sandbox Code Playgroud)

我得到警告Left side of nil coalescing operator '??' has non-optional type 'String??', so the right side is never used和错误:'try?' cannot appear to the right of a non-assignment operator

如果我试一试?括号内的:

guard let x = (try? f("a")) ??
              (try? f("b")) ??
              (try? f("c")) else {
    print("Couldn't get a valid value for x")
    return
}
Run Code Online (Sandbox Code Playgroud)

它可以编译,但是x是可选的,我希望将其解包。

如果我删除问号:

guard let x = (try f("a")) ??
              (try f("b")) ??
              (try f("c")) else {
    print("Couldn't get a valid value for x")
    return
}
Run Code Online (Sandbox Code Playgroud)

我得到了错误Operator can throw but expression is not marked with 'try'

我正在使用Swift 4.2(在撰写本文时,这是Xcode中的最新版本)。

这样做的正确方法是什么x

更新:* f()的返回类型为String?。我认为这是一个可选字符串这一事实很重要。

Ham*_*ish 5

一个try可以覆盖整个表达式,所以你可以说:

  guard let x = try f("a") ?? f("b") ?? f("c") else {
    print("Couldn't get a valid value for x")
    return
  }
Run Code Online (Sandbox Code Playgroud)

同样适用于try?

  guard let x = try? f("a") ?? f("b") ?? f("c") else {
    print("Couldn't get a valid value for x")
    return
  }
Run Code Online (Sandbox Code Playgroud)

尽管请注意,在 Swift 4.2x中将是String?由于您正在应用try?一个已经可选的值,为您提供了一个双重包装的可选值,它guard let只会解开一层。

为了解决这个问题,你可以合并到nil

  guard let x = (try? f("a") ?? f("b") ?? f("c")) ?? nil else {
    print("Couldn't get a valid value for x")
    return
  }
Run Code Online (Sandbox Code Playgroud)

但是在 Swift 5 中这是不必要的,因为SE-0230try? f("a") ?? f("b") ?? f("c")编译器会自动将其中展平为单个可选值。

  • Swift < 5 的替代方案是(双)可选模式:`guard case let x?? = 试试?F A”) ??f("b") ?? f("c")` (2认同)