Swift 为什么通过防止 NIL 展开可选的行不通
Swift why unwrapping optional by guarding against NIL is not working
我是 Swift 的新手,但对可选展开的行为很好奇。
是否有任何解释为什么防止 != nil
不展开可选的?
举个简单的例子:
func hasC(_ s: String?) -> Bool {
guard s != nil else {
return false
}
return s!.contains("c")
}
我需要放置感叹号并显式展开值,尽管在最后一行似乎很清楚 s
不再是可选字符串。
我很想听听这种行为背后的原因,以及在这种情况下如何正确解包值?
创建额外的变量看起来很难看:
guard let s = s else { ... }
并且防止非布尔条件不起作用:
guard s else { ... }
您没有使用 guard 声明新变量,函数参数是可选的,因此即使在 guard 语句之后它也允许您解包
func hasC(_ s: String?) -> Bool {
if let containsValueInString = s , containsValueInString.contains("c"){
return true
}
return false
}
或者更简单,您可以使用带有 nil 合并运算符的可选链接
func hasC(_ s: String?) -> Bool {
return s?.contains("c") ?? false
}
s
的类型仍然是 Optional
,因此您是否进行了 nil
检查是无关紧要的。 nil
检查在运行时完成,而类型系统正在执行编译时检查。确保 s
永远不会是 nil
的唯一方法是通过可选绑定 if let
或 guard let
.
guard
不会单独打开任何东西。这就像一种特殊的 if
。 guard let
展开,但它只是一个语法糖。
简单的答案是等号运算符,例如==
、!=
或任何比较运算符与从编译器的角度展开可选值无关。
guard
语句有 2 个一般用例。一种是防止 boolean
值,它是由等式或比较运算符生成的,如下例所示:
guard ["foo", "bar"].contains("foo") == true else { return }
guard 10 > 5 else { return }
而 guard
语句的另一个作用是解包可选值,它是用 guard let
或 guard var
语法编写的。例如:
guard let unwrappedValue = anOptionalValue else { return }
该特定语法让编译器知道您正在尝试解包该值,如果解包成功,您将得到一个解包值。
当然,虽然创建另一个 variable/constant 可能看起来 "ugly",但这是进入 Swift 的方法。
您使用的格式有误
func hasC(_ s: String?) -> Bool {
guard let input = s else {return false}
return input.contains("c")
}
你可以这样做:
func hasC(_ s: String?) -> Bool {
if let input = s {
return input.contains("c")
}
return false
}
或者您可以像这样使输出可为空:
func hasC(_ s: String?) -> Bool? {
return s?.contains("c")
}
或
func hasC(_ s: String?) -> Bool {
return s?.contains("c") ?? false
}
不丑了。用较低的线。
最好的问候
我是 Swift 的新手,但对可选展开的行为很好奇。
是否有任何解释为什么防止 != nil
不展开可选的?
举个简单的例子:
func hasC(_ s: String?) -> Bool {
guard s != nil else {
return false
}
return s!.contains("c")
}
我需要放置感叹号并显式展开值,尽管在最后一行似乎很清楚 s
不再是可选字符串。
我很想听听这种行为背后的原因,以及在这种情况下如何正确解包值?
创建额外的变量看起来很难看:
guard let s = s else { ... }
并且防止非布尔条件不起作用:
guard s else { ... }
您没有使用 guard 声明新变量,函数参数是可选的,因此即使在 guard 语句之后它也允许您解包
func hasC(_ s: String?) -> Bool {
if let containsValueInString = s , containsValueInString.contains("c"){
return true
}
return false
}
或者更简单,您可以使用带有 nil 合并运算符的可选链接
func hasC(_ s: String?) -> Bool {
return s?.contains("c") ?? false
}
s
的类型仍然是 Optional
,因此您是否进行了 nil
检查是无关紧要的。 nil
检查在运行时完成,而类型系统正在执行编译时检查。确保 s
永远不会是 nil
的唯一方法是通过可选绑定 if let
或 guard let
.
guard
不会单独打开任何东西。这就像一种特殊的 if
。 guard let
展开,但它只是一个语法糖。
简单的答案是等号运算符,例如==
、!=
或任何比较运算符与从编译器的角度展开可选值无关。
guard
语句有 2 个一般用例。一种是防止 boolean
值,它是由等式或比较运算符生成的,如下例所示:
guard ["foo", "bar"].contains("foo") == true else { return }
guard 10 > 5 else { return }
而 guard
语句的另一个作用是解包可选值,它是用 guard let
或 guard var
语法编写的。例如:
guard let unwrappedValue = anOptionalValue else { return }
该特定语法让编译器知道您正在尝试解包该值,如果解包成功,您将得到一个解包值。
当然,虽然创建另一个 variable/constant 可能看起来 "ugly",但这是进入 Swift 的方法。
您使用的格式有误
func hasC(_ s: String?) -> Bool {
guard let input = s else {return false}
return input.contains("c")
}
你可以这样做:
func hasC(_ s: String?) -> Bool {
if let input = s {
return input.contains("c")
}
return false
}
或者您可以像这样使输出可为空:
func hasC(_ s: String?) -> Bool? {
return s?.contains("c")
}
或
func hasC(_ s: String?) -> Bool {
return s?.contains("c") ?? false
}
不丑了。用较低的线。 最好的问候