为啥数组越界抛异常而字典确不会?

数组遭受了不平等对待吗?

在我们访问数组的时候,如果发生了越界,那么我们一定会收到错误。以swift语言为例。

let array = [1,2,3]
array[10] // error !!!!!!!!!

数组中只包含三个元素,但我们用下标10去访问,发生越界错误。

但是当我们访问一个不在字典中的元素的时候,确不会发生类似的情况!

let dic = ["a": 1, "b": 2]
dic["z"]  // 虽然不存在,但不会出现异常

同样的问题,不同的待遇,这是为啥呢?

究其原因

我们来查看一下swift中数组和字典下标访问的实现。

struct Array {
    subscript(index: Int) -> Element
}

struct Dictionary {
    subscript(key: Key) -> Value?
}

比较两者的实现,我们可以得到问题的原因:

  • 数组下标访问返回的不是一个optional类型
  • subscript方法无法throw错误

所以对于数组而言,swift除了弄个fatalError以外,没有其它的替代方案了。而字典返回的是optional类型值,如果发生什么意外状况,即使subscript不能throw errors,字典也可以悠然的返回一个nil。

让我们定义另个版本

其实我们可以给数组做一个扩展,实现一个即使数组访问越界也不会抛异常的版本。

extension Array {
    subscript(safe index: Int) -> Element? {
        return index >= 0 && index < count ? self[index] : nil
    }
}

我们使用 extension 关键字来给Array做一个扩展,要注意的是:我们无法覆盖原有的subscript方法,

注意:subscript方法是可以被重载的,也就是说允许同时有多个subscript方法存在

我们只增加一个新的subscript方法,并明确指定一个外部参数就可以了,我们现在可以这样访问数组了。

var array = [1,2,3]
array[safe: 10] // 返回nil,而不是异常

我们需要在下标访问的时候增加一个label,这个时候虽然我们越界了,但我们却像字典那样,收获了一个nil。

本文的目的是讨论一下字典与数组下标实现的区别以及subscript的一些特点:不可throw,可以重载等
但绝对不是在说数组越界后应该不应该抛出异常。抛不抛出异常要从数组的数据结构应用场景等多方面考虑。

你可能感兴趣的:(为啥数组越界抛异常而字典确不会?)