使用 Swift 字符串的可选链接
Optional chaining with Swift strings
使用可选链接,如果我有一个 Swift 变量
var s: String?
s 可能包含 nil,或者包含在 Optional 中的字符串。所以,我试过这个来获得它的长度:
let count = s?.characters?.count ?? 0
然而,编译器想要这样:
let count = s?.characters.count ?? 0
我对可选链的理解是,一旦您开始在点分表达式中使用 ?.
,其余属性将变为可选并且通常由 ?.
而不是 [=17] 访问=].
所以,我进一步挖掘并在操场上尝试了这个:
var s: String? = "Foo"
print(s?.characters)
// Output: Optional(Swift.String.CharacterView(_core: Swift._StringCore(_baseAddress: 0x00000001145e893f, _countAndFlags: 3, _owner: nil)))
结果表明s?.characters
确实是一个Optional实例,表明s?.characters.count
应该是非法的。
有人可以帮助我了解这种情况吗?
当你说:
My understanding of optional chaining is that, once you start using ?.
in a dotted expression, the rest of the properties are made optional and are typically accessed by ?.
, not .
.
我会说你快到了。
不是所有的属性都可选,而是原来的调用是可选的,所以看起来其他属性都是可选的。
characters
不是可选的 属性,count
也不是,但是您调用它的值是可选的。如果有一个值,那么 characters
和 count
属性将 return 一个值;否则,nil
是 returned。正因为如此,s?.characters.count
return 的结果是 Int?
.
如果其中一个属性是可选的,那么您需要向其添加 ?
,但在您的情况下,它们不是。所以你没有。
已编辑以下评论
来自评论:
I still find it strange that both s?.characters.count
and (s?.characters)?.count
compile, but (s?.characters).count
doesn't. Why is there a difference between the first and the last expression?
我会尽量在这里回答,这里比评论区有更多空间:
s?.characters.count
如果 s
为 nil,则整个表达式 return 为 nil
,否则为 Int
。所以 return 类型是 Int?
.
(s?.characters).count // Won’t compile
分解:如果 s
是 nil
,那么 (s?.characters)
就是 nil
,所以我们不能调用 count
。
为了在 (s?.characters)
上调用 count
属性,需要选择性地展开表达式,即写成:
(s?.characters)?.count
编辑以进一步添加
我能得到的最好的解释是用这段游乐场代码:
let s: String? = "hello"
s?.characters.count
(s?.characters)?.count
(s)?.characters.count
((s)?.characters)?.count
// s?.characters.count
func method1(s: String?) -> Int? {
guard let s = s else { return nil }
return s.characters.count
}
// (s?.characters).count
func method2(s: String?) -> Int? {
guard let c = s?.characters else { return nil }
return c.count
}
method1(s)
method2(s)
在 Swift-users 邮件列表中,Ingo Maier 非常友好地向我指出 Swift 语言规范中的 section on optional chaining expressions,其中指出:
If a postfix expression that contains an optional-chaining expression is nested inside other postfix expressions, only the outermost expression returns an optional type.
继续示例:
var c: SomeClass?
var result: Bool? = c?.property.performAction()
这解释了为什么编译器需要 s?.characters.count 在我上面的例子中,我认为它回答了最初的问题。然而,正如@Martin R 在评论中观察到的那样,编译器为何对这两个表达式进行不同处理仍然是个谜:
s?.characters.count
(s?.characters).count
如果我正确阅读规范,子表达式
(s?.characters)
是"nested inside"整体后缀表达式
(s?.characters).count
因此应与未加括号的版本一样对待。但这是一个单独的问题。
感谢大家的贡献!
使用可选链接,如果我有一个 Swift 变量
var s: String?
s 可能包含 nil,或者包含在 Optional 中的字符串。所以,我试过这个来获得它的长度:
let count = s?.characters?.count ?? 0
然而,编译器想要这样:
let count = s?.characters.count ?? 0
我对可选链的理解是,一旦您开始在点分表达式中使用 ?.
,其余属性将变为可选并且通常由 ?.
而不是 [=17] 访问=].
所以,我进一步挖掘并在操场上尝试了这个:
var s: String? = "Foo"
print(s?.characters)
// Output: Optional(Swift.String.CharacterView(_core: Swift._StringCore(_baseAddress: 0x00000001145e893f, _countAndFlags: 3, _owner: nil)))
结果表明s?.characters
确实是一个Optional实例,表明s?.characters.count
应该是非法的。
有人可以帮助我了解这种情况吗?
当你说:
My understanding of optional chaining is that, once you start using
?.
in a dotted expression, the rest of the properties are made optional and are typically accessed by?.
, not.
.
我会说你快到了。
不是所有的属性都可选,而是原来的调用是可选的,所以看起来其他属性都是可选的。
characters
不是可选的 属性,count
也不是,但是您调用它的值是可选的。如果有一个值,那么 characters
和 count
属性将 return 一个值;否则,nil
是 returned。正因为如此,s?.characters.count
return 的结果是 Int?
.
如果其中一个属性是可选的,那么您需要向其添加 ?
,但在您的情况下,它们不是。所以你没有。
已编辑以下评论
来自评论:
I still find it strange that both
s?.characters.count
and(s?.characters)?.count
compile, but(s?.characters).count
doesn't. Why is there a difference between the first and the last expression?
我会尽量在这里回答,这里比评论区有更多空间:
s?.characters.count
如果 s
为 nil,则整个表达式 return 为 nil
,否则为 Int
。所以 return 类型是 Int?
.
(s?.characters).count // Won’t compile
分解:如果 s
是 nil
,那么 (s?.characters)
就是 nil
,所以我们不能调用 count
。
为了在 (s?.characters)
上调用 count
属性,需要选择性地展开表达式,即写成:
(s?.characters)?.count
编辑以进一步添加
我能得到的最好的解释是用这段游乐场代码:
let s: String? = "hello"
s?.characters.count
(s?.characters)?.count
(s)?.characters.count
((s)?.characters)?.count
// s?.characters.count
func method1(s: String?) -> Int? {
guard let s = s else { return nil }
return s.characters.count
}
// (s?.characters).count
func method2(s: String?) -> Int? {
guard let c = s?.characters else { return nil }
return c.count
}
method1(s)
method2(s)
在 Swift-users 邮件列表中,Ingo Maier 非常友好地向我指出 Swift 语言规范中的 section on optional chaining expressions,其中指出:
If a postfix expression that contains an optional-chaining expression is nested inside other postfix expressions, only the outermost expression returns an optional type.
继续示例:
var c: SomeClass?
var result: Bool? = c?.property.performAction()
这解释了为什么编译器需要 s?.characters.count 在我上面的例子中,我认为它回答了最初的问题。然而,正如@Martin R 在评论中观察到的那样,编译器为何对这两个表达式进行不同处理仍然是个谜:
s?.characters.count
(s?.characters).count
如果我正确阅读规范,子表达式
(s?.characters)
是"nested inside"整体后缀表达式
(s?.characters).count
因此应与未加括号的版本一样对待。但这是一个单独的问题。
感谢大家的贡献!