Swift 数组[index]没有';不返回可选的?

Swift 数组[index]没有';不返回可选的?,swift,Swift,我觉得array[index]应该返回一个可选的,因为索引可能超出范围 这将允许使用以下代码: 如果让对象=数组[索引]{ //做事 } 使用扩展方法很容易做到这一点,但了解这种情况的真正原因将是一件好事。 它取决于数组元素的类型。例如,如果将数组定义为 var arr:[String?] = Array<String?>(count: 5, repeatedValue: "SomeString") var arr:[String?]=数组(计数:5,repeatedValue:“

我觉得
array[index]
应该返回一个可选的,因为索引可能超出范围

这将允许使用以下代码:

如果让对象=数组[索引]{
//做事
}
使用扩展方法很容易做到这一点,但了解这种情况的真正原因将是一件好事。

它取决于数组元素的类型。例如,如果将数组定义为

var arr:[String?] = Array<String?>(count: 5, repeatedValue: "SomeString")
var arr:[String?]=数组(计数:5,repeatedValue:“SomeString”)
然后,
array[index]
将是可选的


但本质上,
array[index]
是一个非可选值,因为访问其边界之外的数组本身会引发异常,更不用说获取其值了。因此,您不会忽略阅读元素本身。

这可能是出于设计。由于很容易获得数组中的项数,如果您从
0迭代到count-1
,则始终会有一个值。如果
array[index]
可以返回nil,那么每次遍历数组时都必须打开一个可选项,这将是一件痛苦的事情:)。

这是其中之一,它被关闭为“行为正确”。还讨论了它。正如Dave Abrahams所指出的:

至于基本原理,很容易也很常见的静态知识是索引在范围内。。。。在这种情况下,最好建立一个前提条件,即索引是有效的,这样普通用例就不必在语法上处理不可能发生的故障。这与对键进行字典索引形成对比,通常不知道键是否已经在字典中

随着我在Swift方面的经验越来越丰富,我逐渐同意了这一点。有时我确实希望有一个内置的“安全下标”(比如),但我同意它不应该是默认值

将其设为默认值将使数组非常难以使用,这不仅是因为需要展开,还因为索引类型将不再是
Int
。要求
下标(索引)
返回
元素
(不是
元素?
)。这就是为什么字典的索引不是键的原因;它是
字典索引
。创建一个特殊的
ArrayIndex
可能会有很多恼人的副作用。(也许最终一切都会成功,但是否值得值得值得怀疑。)

这里真正的教训是,无论如何都应该避免任意订阅数组。如果可行,您应该更愿意将其用作
集合类型
。这意味着只订阅您获取的索引(例如使用
indexOf
indexOf
),并且强烈支持迭代(
对于in
map
),而不是订阅。首先使用
xs.first
而不是
xs[0]
。如果将其视为一个集合而不是数组,则可以获得所描述的安全性,同时在需要解决知道下标在范围内的特殊问题时,仍保留可用下标

这里有一个说明性的例子。考虑这个常见的循环,您可能认为需要下标:

let xs = [1,2,3]

for i in 0..<xs.count {
    print("\(i): \(xs[i])")
}
但即使这样也没有必要。我们可以做得更好,使其适用于所有序列:

for (i, x) in xs.enumerate() {
    print("\(i): \(x)")
}

不需要下标。

请尝试查看以下示例:

var-arr:Array=[]
arr.append(1)
arr.append(无)
arr.count==2
设n=arr[1]//nil
我认为用这个例子很容易理解原因。即使您的索引有效,您仍然会收到
nil

因此,我们知道类型,但是:

如果让n=arr[1]{
//如何知道索引是否超出范围
//还是返回了有效的nil值?
}

考虑到user3441734:s答案下的详尽讨论(我们可能应该在chat中使用…),我觉得我必须澄清我认为user3441734试图表达的有点确定的观点

首先,请注意,问题包括

  • Swift让无效索引情况像这样运行(抛出异常,超出范围),而不是返回可选索引的原因是什么
Rob的答案是详尽的,并且很好地涵盖了这一点,但我确实认为user3441734:s的答案至少应该是状态>=0,因为它确实包含了另一个原因,即假设的案例“swift让无效索引返回可选”可能不是一个好主意。请注意,决不是“…真正的原因…”swift不让无效索引返回零,但我认为这一点值得>=0票

问题不包括:

  • 如果索引超出范围,是否可以获取可选的而不是异常
问题作者自己说“用扩展方法很容易做到”


因此,现在让我们来看看用户3441734:s的答案,并尝试让它更清楚地告诉我们他/她试图指出什么

我们将分析以下表达式,假设我们处于一个平行的Swift宇宙中,其中无效索引情况(w.r.t.数组)被视为可选,并返回
nil

// Lets assume the following is all in the scope of some function
var arr: Array<Int?> = []
arr.append(1)
arr.append(nil)
arr.append(3)
print("\(arr)") // Optional(1), nil, Optional(3)

// lets say the function randomIntegerTwoOrFour() -> Int returns, 
// randomly, either value 2 or value 4.
let ourMagicAndAtCompileTimeUnknownIndex = randomIntegerTwoOrFour()

// now, in our parallel Swift universe, say we want to
// use an if let clause on our array at our magic index
if let n = arr[ourMagicAndAtCompileTimeUnknownIndex] {
    // ...
}
else {
    // lets say we're not careful here, and think that we've
    // entered this clause because of a nil valued member of
    // our array. If we try to use our magic index for non-nil
    // assignment, how would parallel universe Swift 2 handle this?
    
    // We could of course try some downcasting to infer actual, 
    // (optional) type ourselves, but this is not very "Swifty" 
    // w.r.t. if let clauses.
}

// on the other hand, say we want to guard against invalid-index
// in our array, using a guard let clause 
guard let n = arr[ourMagicAndAtCompileTimeUnknownIndex] else {
    print("Out of bounds!") 
         // or are we ...? Careful parallel Swift universe programmer!
    
    // Naturally, we could (and should, in parallel Swift 2 universe), 
    // look closer at what type n is at this point, but this is also
    // not very "Swifty" in this context).

    return
}
//假设以下内容都在某个函数的范围内
var arr:Array=[]
arr.append(1)
arr.append(无)
附件(3)
打印(\(arr)//可选(1)、无、可选(3)
//假设函数randomIntegerTwoOrFour()->Int返回,
//随机选择值2或值4。
让我们的magicanDatCompileTimeUnknownIndex=randomIntegerTwoOrFour()
//现在,在我们平行的迅捷宇宙中,我们想
//在我们的魔术索引数组上使用if-let子句
如果让n=arr[ourmagicandatcomiletimeunknownindex]{
// ...
}
否则{
//假设我们在这里不小心,并认为我们
//由于无值成员而输入此子句
// Lets assume the following is all in the scope of some function
var arr: Array<Int?> = []
arr.append(1)
arr.append(nil)
arr.append(3)
print("\(arr)") // Optional(1), nil, Optional(3)

// lets say the function randomIntegerTwoOrFour() -> Int returns, 
// randomly, either value 2 or value 4.
let ourMagicAndAtCompileTimeUnknownIndex = randomIntegerTwoOrFour()

// now, in our parallel Swift universe, say we want to
// use an if let clause on our array at our magic index
if let n = arr[ourMagicAndAtCompileTimeUnknownIndex] {
    // ...
}
else {
    // lets say we're not careful here, and think that we've
    // entered this clause because of a nil valued member of
    // our array. If we try to use our magic index for non-nil
    // assignment, how would parallel universe Swift 2 handle this?
    
    // We could of course try some downcasting to infer actual, 
    // (optional) type ourselves, but this is not very "Swifty" 
    // w.r.t. if let clauses.
}

// on the other hand, say we want to guard against invalid-index
// in our array, using a guard let clause 
guard let n = arr[ourMagicAndAtCompileTimeUnknownIndex] else {
    print("Out of bounds!") 
         // or are we ...? Careful parallel Swift universe programmer!
    
    // Naturally, we could (and should, in parallel Swift 2 universe), 
    // look closer at what type n is at this point, but this is also
    // not very "Swifty" in this context).

    return
}