tl; dr
Est-il possible d'instancier un membre enum Swift 4 enum avec une valeur associée de type Void
?
Contexte
J'utilise une énumération simple Result (similaire à Résultat antitypical ):
enum Result<T> {
case success(T)
case error(Error?)
}
Maintenant, je voudrais utiliser cette énumération pour représenter le résultat d'une opération qui ne donne pas de valeur de résultat réelle; l'opération est soit réussi ou échoué. Pour cela, je définirais le type comme Result<Void>
, Mais je n'arrive pas à créer l'instance de résultat, ni let res: Result<Void> = .success
Ni let res: Result<Void> = .success()
ne fonctionne.
Dans Swift 3, vous pouvez omettre la valeur associée de type Void
:
let res: Result<Void> = .success()
Dans Swift 4 vous devez passer une valeur associée de type Void
:
let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())
Dans Swift 4, un cas d'énumération avec une valeur associée Void
n'est plus équivalent à un cas d'énumération avec une liste vide de valeurs associées.
Je crois que c'est, comme Martin dit , un résultat de SE-0029 où vous ne pouvez plus passer un Tuple d'arguments à une fonction et les avoir "splat" à travers le paramètres (bien que la proposition ait été marquée comme implémentée en Swift 3, je crois que ce cas particulier a été repris plus tard dans l'implémentation de SE-011 for Swift 4).
Par conséquent, cela signifie que vous ne pouvez plus appeler un (Void) -> T
comme un () -> T
in Swift 4. Vous devez maintenant passer Void
explicitement:
let result = Result.success(())
Cependant, je trouve cela assez moche, donc j'implémente généralement une extension comme celle-ci:
extension Result where T == Void {
static var success: Result {
return .success(())
}
}
Ce qui vous permet de dire des choses comme ça:
var result = Result.success
result = .success
Il convient de noter que cette solution de contournement ne se limite pas aux cas d'énumération, elle peut également être utilisée avec des méthodes en général. Par exemple:
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()
Void est une simple typealias pour un Tuple vide: () afin que vous puissiez l'utiliser comme suit:
let res1: Result<Void> = .success(())
let res2 = Result<Void>.success(())
let res3 = Result.success(() as Void)
let res4 = Result.success(())