Swift中Collection扩展为何出现Int无法转为Self.Index错误?
问题分析与解决
错误原因
你犯的核心错误是想当然认为Collection的Index一定是Int类型,但实际上Collection协议里的Index是个关联类型,它只要求遵循Comparable和Hashable,具体类型由不同的Collection实现决定:
- 比如
String的索引是String.Index,不是整数,它是用来定位Unicode字符的复杂类型; Dictionary的索引是Dictionary.Index,同样不是Int;- 只有像
Array这种连续存储的集合,Index才是Int,但你写的是通用的Collection扩展,要适配所有实现了该协议的类型,所以不能硬用0来判断。
你用0(Int类型)去调用indices.contains(_:),而这个方法需要的参数是Self.Index类型,类型不匹配自然报错。错误提示的as! Self.Index完全不可取——强制类型转换在非Int类型的Index上会直接崩溃,比如对String用这个转换,程序直接挂掉。
正确实现方式
判断Collection是否有首个元素,本质就是判断集合是否非空,直接用!isEmpty就足够了,或者更底层一点用startIndex != endIndex(isEmpty的默认实现就是基于这个判断的)。修正后的扩展代码如下:
extension Collection { var firstOneExist: Bool { !isEmpty } }
补充说明
如果你的需求是更严谨地判断“首个元素的位置是否存在”,那直接用startIndex != endIndex也完全等价,因为Collection的startIndex指向第一个元素的位置,当集合为空时,startIndex等于endIndex。
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

