在 Swift 中为可选项提供默认值?

在 Swift 中处理可选项的习惯用法似乎过于冗长,如果你想做的只是在它为 nil 的情况下提供一个默认值:

if let value = optionalValue {
// do something with 'value'
} else {
// do the same thing with your default value
}

包括不必要地复制代码,或者

var unwrappedValue
if let value = optionalValue {
unwrappedValue = value
} else {
unwrappedValue = defaultValue
}

它要求 unwrappedValue不是常数。

Scala 的 Option monad (和 Swift 的 Option 基本上是同一个概念)为此使用了 getOrElse方法:

val myValue = optionalValue.getOrElse(defaultValue)

我错过了什么吗?斯威夫特已经有一个简洁的方法来做这件事了吗?或者,如果做不到这一点,是否有可能在可选的扩展中定义 getOrElse

88160 次浏览

下面的方法似乎行得通

extension Optional {
func getOrElse<T>(defaultValue: T) -> T {
if let value = self? {
return value as T
} else {
return defaultValue
}
}
}

然而,需要施放 value as T是一个丑陋的黑客。理想情况下,应该有一种方法来断言 T与可选项中包含的类型相同。实际情况是,类型推断基于给 getOrElse 的参数设置 T,如果这个参数不匹配可选参数,并且可选参数不为零,那么在运行时就会失败:

let x: Int?


let y = x.getOrElse(1.414) // y inferred as Double, assigned 1.414


let a: Int? = 5


let b: Double = a.getOrElse(3.14) // Runtime failure casting 5 to Double

更新

苹果现在增加了一个合并运营商:

var unwrappedValue = optionalValue ?? defaultValue

在这种情况下,三元操作符是你的朋友

var unwrappedValue = optionalValue ? optionalValue! : defaultValue

您还可以为可选枚举提供自己的扩展:

extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}

然后你可以这样做:

optionalValue.or(defaultValue)

然而,我建议坚持使用三元操作符,因为其他开发人员不需要研究 or方法就能更快地理解这一点

注意 : 我启动了一个 模组,将类似于 Optional上的 or这样的常见助手添加到 Swift。

截至2014年8月,斯威夫特有聚结运营商(? ?)允许这样的事情发生。例如,对于一个可选的 String myOptions,您可以写:

result = myOptional ?? "n/a"

如果你写道:

let result = optionalValue ?? 50

optionalValue != nil然后 result将是 optional也,你将来需要拆开它

但是你可以写操作符

infix operator ??? { associativity left precedence 140 }


func ???<T>(optLeft:T?, right:T!) -> T!
{
if let left = optLeft
{
return left
}
else { return right}
}

现在你可以:

 let result = optionalValue ??? 50

optionalValue != nil时,result就是 unwraped

如果你想用 String 做这个,你可以这样做。

string1 = string2.isEmpty ? "Default Value":string2