具有Void关联类型的Generic Swift 4枚举

dr_*_*rto 31 enums swift swift4

TL;博士

是否可以实例化具有相关类型值的通用Swift 4枚举成员Void

背景

我正在使用一个简单的结果枚举(类似于antitypical结果):

enum Result<T> {
  case success(T)
  case error(Error?)
}
Run Code Online (Sandbox Code Playgroud)

现在我想用这个枚举来表示一个不产生实际结果值的操作的结果; 操作成功失败.为此,我将类型定义为Result<Void>,但我正在努力如何创建Result实例,既不起作用let res: Result<Void> = .successlet res: Result<Void> = .success()不起作用.

Mar*_*n R 61

在Swift 3中,您可以省略类型的关联值Void:

let res: Result<Void> = .success()
Run Code Online (Sandbox Code Playgroud)

在Swift 4中,您必须传递类型的关联值Void:

let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())
Run Code Online (Sandbox Code Playgroud)

  • 是否有一个不那么难看的解决方案? (11认同)

Ham*_*ish 33

在Swift 4中,具有Void关联值的枚举案例不再等同于具有关联值的空列表的枚举案例.

我相信,正如马丁所说,这是SE-0029的结果,你不能再将一个参数元组传递给一个函数并让它们"跨越"参数(虽然该提议已在Swift 3中实现,我相信这个特殊情况后来在Swift 4 的SE-0110实施中被提到.

其结果是,这意味着你可以不再调用(Void) -> T作为() -> T斯威夫特4.您现在必须通过Void明确:

let result = Result.success(())
Run Code Online (Sandbox Code Playgroud)

但是,我觉得这很难看,所以我通常会实现这样的扩展:

extension Result where Success == Void {
    static var success: Result {
        return .success(())
    }
}
Run Code Online (Sandbox Code Playgroud)

这让你说出这样的话:

var result = Result.success
result = .success
Run Code Online (Sandbox Code Playgroud)

值得注意的是,这种解决方法不仅限于枚举案例,它还可以与一般的方法一起使用.例如:

struct Foo<T> {
  func bar(_ a: T) {}
}

extension Foo where T == Void {
  func bar() { bar(()) }
}

let f = Foo<Void>()

// without extension:
f.bar(())

// with extension:
f.bar()
Run Code Online (Sandbox Code Playgroud)

  • ((尼斯)).没有意识到你可以根据泛型的类型定义变量. (3认同)

小智 5

Void 是空元组的简单类型别名:(),因此您可以将其用作以下任何一种:

let res1: Result<Void> = .success(())
let res2 = Result<Void>.success(())
let res3 = Result.success(() as Void)
let res4 = Result.success(())
Run Code Online (Sandbox Code Playgroud)