在Swift中,为什么
var x: Int? = nil
if let y: Int? = x { ... }
表现与
不同if let y: Int? = nil { ... }
我understanding为什么第一个案例成功的原因表明第二个案例也应该如此,所以我一定不能理解。
后者由于分配无效而没有失败,也没有因为可选链接而失败;否则它看起来和前者一样。为什么后者失败了,它与前者有何不同。究竟在什么时候,以及为什么原因,第二个可选绑定被放弃了?
答案 0 :(得分:9)
if let y: Int? = nil { ... }
相当于
if let y: Int? = nil as Int?? { ... }
相当于
if let y: Optional<Int> = Optional<Optional<Int>>() { ... }
这会尝试将Optional<Optional<Int>>
转换为Optional<Int>
,但由于Optional<Optional<Int>>()
不包含Optional<Int>
值而失败,因此会失败。
Oneliner相当于
var x: Int? = nil
if let y: Int? = x { ... }
是
if let y: Int? = nil as Int? { ... }
增加:
我在What does Swift's optional binding do to the type it's arguments?回答。
if let y: Int? = nil as Int? { ... }
编译为:
if let y:Int? = nil as Int? as Int?? { ... }
在这里,我们应该注意nil as Int? as Int??
不等同于nil as Int??
。
前者为Optional(Optional<Int>())
,后者为Optional<Optional<Int>>()
。
考虑到这一点,我想,
所以我的第一个例子中的可选绑定(确实)“检查内部”并找到nil,这对于分配给Int是完全有效的吗?但我的第二次检查并找到Optional(nil),它不能分配给Int?
Int??
的第一个“检查内部”示例,只找到Optional<Int>()
类型的Int?
值,该值可以分配给Int?
;但是第二个发现 nothing 被分配并失败。
答案 1 :(得分:1)
let
declares a constant。使用带有let
的{{1}}语句中的if
,然后将初始化常量绑定到 failable 初始化程序的结果,而不是字面上{{1}或另一个文字。
编译器允许您直接使用Optional<T>
,而不是&#39; 4&#39;例如,因为nil
在Optional之外具有use / context;但是,nil
的这种文字使用绕过了初始化程序,因此没有结果可以绑定。在4或Int(4)的情况下,编译器知道某些内容是错误的并且不会编译。
查看以下示例:
nil
......输出:
nil
更新:解释var xnil: Int? = nil
var x4: Int? = Int?(4)
var xnone: Int? = Int?()
var xdefault: Int? = Int()
if let znil: Int? = nil {
println("znil:\(znil)")
} else {
println("znil: did not bind")
}
if let zn0: Int? = Int?(nilLiteral: ()) {
println("zn0:\(zn0)")
}
if let zn1: Int? = Int?(()) {
println("zn1:\(zn1)")
}
if let zn2: Int? = Int?() {
println("zn1:\(zn2)")
}
if let zn3: Int? = Int?.None {
println("zn3:\(zn3)")
}
if Int?.None == nil {
println(".None == nil")
}
if let zo0: Int? = Int?(4) {
println("zo0:\(zo0)")
}
//nil-test.swift:36:20: error: bound value in a conditional binding must be of Optional type
//if let zo1: Int? = 4 {
// ^
/*
if let zo1: Int? = 4 {
println("zo1:\(zo1)")
}
*/
//nil-test.swift:51:20: error: bound value in a conditional binding must be of Optional type
//if let zo2: Int? = Int(4) {
// ^
/*
if let zo2: Int? = Int(4) {
println("zo2:\(zo2)")
}
*/
if let zxn0: Int? = xnil {
println("zxn0:\(zxn0)")
}
if let zxn1: Int? = x4 {
println("zxn1:\(zxn1)")
}
if let zxn2: Int? = xnone {
println("zxn2:\(zxn2)")
}
if let zxn3: Int? = xdefault {
println("zxn3:\(zxn3)")
}
和znil: did not bind
zn0:nil
zn1:nil
zn1:nil
zn3:nil
.None == nil
zo0:Optional(4)
zxn0:nil
zxn1:Optional(4)
zxn2:nil
zxn3:Optional(0)
之间的区别。
见这个例子:
Type
......输出:
Type?
...所以,问问自己:
if let a: Int? = nil {
println("a: \(a)")
} else {
println("a: let fail")
}
if let b1: Int? = Int?(nilLiteral: ()) { // same as Int?() -- added nilLiteral to be explicit here
println("b1: \(b1)")
}
if let b2: Int? = Int?(44) {
println("b2: \(b2); b2!: \(b2!)")
}
if let c1: Int = Int?(44) {
println("c1: \(c1)")
}
if let c2: Int = Int?(nilLiteral: ()) { // Again, Int?() would suffice
println("c2: \(c2)")
} else {
println("c2: let fail")
}
/// NOTE: these 'd' examples represents a more idiomatic form
var m: Int? = Int?()
if let d1 = m {
println("d1: \(d1)")
} else {
println("d1: let fail")
}
m = Int?(444)
if let d2 = m {
println("d2: \(d2)")
} else {
println("d2: let fail")
}
m = Int?()
println("m?: \(m?)")
if let whyDoThis: Int? = m {
println("whyDoThis?: \(whyDoThis?) -- the `let` is telling you nothing about 'm!'")
}
失败,a: let fail
b1: nil
b2: Optional(44); b2!: 44
c1: 44
c2: let fail
d1: let fail
d2: 444
m?: nil
whyDoThis?: nil -- the `let` is telling you nothing about 'm!'!
绑定成功,即使它包含零值?a
在此时明确包含零值时,b1
为什么会成功?if let whyDoThis ...
的价值告诉您m
的哪些内容?最后,对于这种情况,惯用的Swift伪代码应该如下所示:
whyDoThis?
更新2:好的,让我们来看看类型......
请参阅以下示例:
m!
......输出:
var maybeT: MyType?
// ... maybe set maybeT to a MyType, maybe not
if let reallyHaveT = maybeT {
// reallyHaveT has a bound value of type MyType
}
我想强调的一点是,当你写var none: Int? = Int?()
var one: Int? = Int?(1)
println("Int() type: \(_stdlib_getTypeName(Int())), val: \(Int())")
println("Int(1) type: \(_stdlib_getTypeName(Int(1))), val: \(Int(1))")
println("Int?() type: \(_stdlib_getTypeName(Int?())), val: \(Int?())")
println("Int?(1) type: \(_stdlib_getTypeName(Int?(1))), val: \(Int?(1))")
println("none type: \(_stdlib_getTypeName(none)), val: \(none)")
println("one type: \(_stdlib_getTypeName(one)), val: \(one)")
if let x = none {
println("`let x = none` x type: \(_stdlib_getTypeName(x))")
} else {
println("`let x = none` FAIL")
}
if let x: Int = none {
println("`let x: Int = none` x type: \(_stdlib_getTypeName(x))")
} else {
println("`let x: Int = none` FAIL")
}
if let x: Int? = none {
println("`let x: Int? = none` x type: \(_stdlib_getTypeName(x))")
}
if let y = one {
println("`let y = one` y type: \(_stdlib_getTypeName(y))")
}
if let y: Int = one {
println("`let y: Int = one` y type: \(_stdlib_getTypeName(y))")
}
if let y: Int? = one {
println("`let y: Int? = one` y type: \(_stdlib_getTypeName(y))")
}
if let z: Int? = nil {
println("`let z: Int? = nil` z type: \(_stdlib_getTypeName(z))")
} else {
println("`let z: Int? = nil` FAIL")
}
if let z = Int?() {
println("`let z = Int?()` z type: \(_stdlib_getTypeName(z))")
} else {
println("`let z = Int?()` FAIL")
}
时,你正在有效地调用Int() type: _TtSi, val: 0
Int(1) type: _TtSi, val: 1
Int?() type: _TtSq, val: nil
Int?(1) type: _TtSq, val: Optional(1)
none type: _TtSq, val: nil
one type: _TtSq, val: Optional(1)
`let x = none` FAIL
`let x: Int = none` FAIL
`let x: Int? = none` x type: _TtSq
`let y = one` y type: _TtSi
`let y: Int = one` y type: _TtSi
`let y: Int? = one` y type: _TtSq
`let z: Int? = nil` FAIL
`let z = Int?()` FAIL
。在let z = Int?()
语句中使用时,这将无法绑定。总是。
答案 2 :(得分:0)
if let
用于删除可选项。如果你想查看变量何时使用
if let y: Int = x {
// This occurs if you are able to give a non-nil value to the variable
} else {
// This occurs if the optional x is nil
}
据我所知,你不应该尝试在if let
语句中声明一个常量的类型是可选的,因为这样会破坏if let语句的用途。