??的定义运营商是:
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
为什么不使用T代替@autoclosure?
像这样:
func ??<T>(optional: T?, defaultValue: T) -> T {
switch optional {
case .some(let value):
return value
case .none:
return defaultValue
}
}
修改:@autoclosure
在效果方面的好处是什么?
答案 0 :(得分:3)
如果你同意你的建议功能
func ??<T>(optional: T?, defaultValue: T) -> T
defaultValue的值将直接在函数体中计算和复制或引用。如果我们实际上永远不会使用这个值,那么在许多情况下计算上的工作量会更多。
例如:
var thatImage: UIImage? = somImage
lazy var image() -> UIImage {
return UIImage(named:"imgName")
}
let newImage = thatImage ?? image()
在这种情况下:
func ??<T>(optional: T?, defaultValue: T) -> T
当编译器评估此thatImage ?? image()
时,它实际调用图像函数并执行工作并返回图像。
但最终我们会丢弃它,因为第一个选项在这种情况下有一个值。
使用@autocolsure,我们不会花时间计算我们不需要的东西。我们推迟计算。
有了这个,
func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
编译器会将表达式推导出来
thatImage ?? image()
- &gt; thatImage ?? {return image() }
声明从字面上变成了这个。
??(thatImage, { return image() } )
并且仅在块内部,如果第一个参数没有值,则编译器将调用该块,然后将执行计算以获取图像。