在Swift中,您可以使用if let可选绑定将可选内容解包为具有相同名称的常量或变量:
func test() { let a: Int? = 1 if let a = a { print("a = \(a)") } }
对于if let语句中的所有内容,可选项都a被包装为常规int。
if let
a
同样,我可以使用保护语句来达到类似的效果
func test() { let a: Int? = 1 guard let requiredA = a else{ return } print("a = \(requiredA)") }
但是,我不能使用这样的代码guard let a = a else:
guard let a = a else
func test() { let a: Int? = 1 guard let a = a else{ return } print("a = \(a)") }
为什么不?
在保护语句中,如果保护语句的条件失败,则执行else子句,然后退出当前作用域。如果条件成功,则将从保护语句的右括号到当前作用域的结尾创建一个新的变量/常量。
为什么我不能做同样的技巧将可选对象映射到具有相同名称的变量/常量,以用于当前作用域的其余部分?
PS: 我知道这个问题并不适合这个网站。对于这个问题在哪里更好,我乐于接受建议。
您无法执行此操作的原因:
因为guard在同一范围内创建新变量,因此您a在同一范围内调用了两个变量。一个是一个Int,另一个是一个Int?。那是不允许的。
guard
Int
Int?
您获得的 定义 错误 与先前的值冲突与执行此 操作完全相同:
func test() { let a: Int? = 1 let a = a! }
与以下内容进行比较:
在这种情况下,新的变量aan Int是仅存在于ifthen子句的新范围内,因此可以正常工作。
if
从评论:
但是我向您提出,右括号之后到封闭范围的末尾的代码部分实际上是一个内部范围。
我可以理解,您希望这样,但事实并非如此。如果是这种情况,那么您可以执行此操作,但同时也会出现错误:
func test() { let a: Int? = 1 guard let b = a else{ return } print("b = \(b)") let a = 5 // Definition conflicts with previous value print("a = \(a)") }
这样做的好处guard在于,它不会创建新的作用域,并且避免创建反复使用来解开可选对象(并在此过程中创建新的作用域)时导致 的死亡金字塔if let。