你能解释一下原因吗:
- 当我使用 array.first 访问数组值时,它是可选的
- 当我从索引值访问时不是吗?
示例:
var players = ["Alice", "Bob", "Cindy", "Dan"]
let firstPlayer = players.first
print(firstPlayer) // Optional("Alice")
let firstIndex = players[0]
print(firstIndex) // Alice
最佳答案
(这个问题的简短答案很好,正是你所需要的。我只是想更深入地了解为什么以及如何更普遍地与 Swift 集合以及底层类型交互。如果你只是想“如何我应该使用这些东西吗?”阅读接受的答案并忽略所有这些。)
数组遵循所有集合的规则。集合必须实现以下下标:
subscript(position: Self.Index) -> Self.Element { get }
所以要成为一个Collection,Array的下标必须接受它的Index并且无条件地返回一个Element。对于很多种类的Collections,不可能创建一个不存在的Index,但是Array使用Int作为它的Index,所以它必须处理你传递一个超出范围的Index的可能性。在那种情况下,返回一个Element是不可能的,它唯一的选择就是根本不返回。这通常采取使程序崩溃的形式,因为它通常比挂起程序更有用,后者是另一种选择。
(这隐藏了一点类型理论,即 Swift 中的每个函数在技术上都可以返回“崩溃”,但我们不会在类型系统中跟踪它。这样做是可能的,以区分函数可以崩溃和那些不能,但 Swift 不会。)
这自然会提出一个问题,即当您使用不存在的键下标时,为什么 Dictionary 不会崩溃。原因是 Dictionary 的 Index 不是它的 Key。它有一个很少使用的下标,它提供对 Collection 的一致性(在顶级代码中很少使用,但在 stdlib 内部非常常用):
subscript(position: Dictionary<Key, Value>.Index) -> Dictionary.Element { get }
Array 也可以做到这一点,拥有一个独立于 Int 的 Array.Index
类型,并使 Int 下标返回一个 Optional。在 Swift 1.0 中,我打开了一个雷达来请求它。该团队争辩说,这会使 Array 的常见使用变得过于困难,而且使用 Swift 的程序员已经习惯了将超出范围视为编程错误(崩溃)的想法。另一方面,字典通常使用不存在的键来访问,因此键下标应该是可选的。多年来使用 Swift 使我确信他们是对的。
一般来说你不应该下标数组除非你从数组中得到索引(即使用index(where:)
)。但是许多 Cocoa 模式使得下标变得非常自然(cellForRow(at:)
是最著名的)。尽管如此,在更纯粹的 Swift 代码中,使用任意 Int 进行下标通常表明存在设计问题。
相反,您应该经常使用 Collection 方法,例如 first
和 first(where:)
,它们返回 Optionals,通常更安全、更清晰,并使用 for 迭代它们-in
循环而不是下标。
关于swift - 数组值是否可选?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49384978/