我正在编写一个名为TriangularArray<T>
的自定义集合。它代表这样的结构:
x
x x
x x x
x x x x
x x x x x
其中每个x
是数组中的元素。我可以使用行号和索引号(都从零开始)访问元素。例如,访问以下内容的(4,2):
a
b c
d e f
g h i j
k l m n o
将得到m
(第5行,该行的第三个值)。
我使用[[T]]
作为后备数组,并编写了这样的下标:
subscript(_ row: Int, _ index: Int) -> T? {
get {
// innerArray is the [[T]] used for backing
if row < 0 || row >= innerArray.count {
return nil
}
if index < 0 || index > row {
return nil
}
return innerArray[row][index]
}
set {
if row < 0 || row >= innerArray.count {
return
}
if index < 0 || index > row {
return
}
innerArray[row][index] = newValue!
}
}
逻辑是,如果您访问不存在的行和索引,如(1,3),则下标将返回nil
。但是,通过使下标返回T?
,在setter中的newValue
也变得可选,我必须强行打开它。
我真的很想在编译时检查这种事情:
triangularArray[0, 0] = nil // this should be a compile time error
我尝试在Google上查找此内容,但我只发现了这个question,这已经过时了。当然,我们可以在Swift 4.2中做得更好,对吧?
答案 0 :(得分:0)
只有Swift 4.2可以帮助您在我们的代码中标记此类问题,但我认为4.1或更低版本是不可能的。
Swift 4.2示例:
#if true
#error("add here your compiler error")
#endif
答案 1 :(得分:0)
不幸的是,由于Swift的大小是动态的,并且在编译时不知道,因此无法与Swift(以及其他使用动态数组的语言)一起使用(在程序运行时可以用任何值初始化)。正在运行)。
例如,如果TriangularArray<T>
的大小为1
,则[0, 0]
是有效元素,并且编译器无法事先知道。
在标准库中,尝试访问array[-1]
之类的数组时没有编译时错误-这将始终编译,但始终会导致运行时错误。
我认为您当前使用可选的解决方案似乎是这里的最佳方案。您还将与Array
的工作方式保持一致,并在给出无效下标时触发fatalError
。
一种替代方法是在Index
中创建一个自定义TriangularArray
结构,该结构表示三角形的索引,并且可以选择使用x
和y
值构建(尽管这会使事情复杂化)相当多。)
PS:此答案假设TriangularArray<T>
可以具有任意高度的三角形(可以在运行时指定高度),因为问题中未指定。如果高度是在编译时定义的,则可以对边界进行硬编码,并且可以像提到的#error
一样使用@Raul Mantilla。