为Swift中的Optional提供默认值?


141

在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的Optional基本相同)具有getOrElse用于此目的的方法:

val myValue = optionalValue.getOrElse(defaultValue)

我想念什么吗?Swift已经有一种紧凑的方式做到这一点吗?否则,是否可以getOrElse在扩展名中为Optional 定义?


Answers:


289

更新资料

苹果现在添加了一个合并运算符:

var unwrappedValue = optionalValue ?? defaultValue

在这种情况下,三元运算符是您的朋友

var unwrappedValue = optionalValue ? optionalValue! : defaultValue

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

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

然后,您可以执行以下操作:

optionalValue.or(defaultValue)

但是,我建议您坚持使用三元运算符,因为其他开发人员无需研究该or方法即可更快地了解这一点。

:我开始一个模块来添加共同佣工像这样orOptional以迅速。


我的编译器向我显示,unwrappedValue在Swift 1.2:var unwrappedValue = optionalValue ? optionalValue! : defaultValue(xcode 6 beta 4)中,这种情况下的类型仍然是可选类型。这改变了吗?
SimplGy

2
我的版本不对。我是6.4。请注意:??默认类型推断行为是它返回可选值,这通常不是您想要的。您可以将变量声明为非可选变量,这样效果很好。
SimplGy 2015年

29

自2014年8月起,Swift具有合并运算符(??),允许该操作。例如,对于可选的字符串myOptional,您可以编写:

result = myOptional ?? "n/a"

4

如果您写道:

let result = optionalValue ?? 50

optionalValue != nil随后resultoptional过,你会需要它展开未来

但是你可以写运算符

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 != nilresultunwraped


3

以下似乎有效

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

但是,投放value as T内容的方法很丑陋。理想情况下,应该有一种断言T与Optional中包含的类型相同的方法。就目前而言,T根据为getOrElse提供的参数键入推理集,然后在运行时失败(如果这与Optional不匹配并且Optional为非nil):

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

您无需T为该方法指定。实际上,这将覆盖TOptional中的现有内容。您可以执行以下操作:func getOrElse(defaultValue: T) -> T然后T表示可选对象的实际值类型,而不必键入检查它
drewag 2014年

谢谢!我准确地从您的回答的后半部分推断出这一点。有什么方法可以检查Optional的定义,以了解泛型类型是按此定义的T吗?(除了基于约定的简单假设之外)
Wes Campaigne

如果Optional在Xcode内单击命令,您将看到它的定义为enum Optional<T>
drewag 2014年

太好了 我应该猜到的。其中的定义将很有用;文档中还没有很多内容。再次感谢。
Wes Campaigne
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.