表现
这两种方法应该具有相当的性能。在底层,它们都在做非常相似的事情:返回一个带有已检查标志的值,并且只有当标志显示结果有效时,才会继续。对于选项,该标志是枚举(.None 与 .Some),其中throws
该标志是一个隐式标志,可触发跳转到 catch 块。
值得注意的是你的两个函数不做同样的事情(一个返回nil
如果没有键匹配,则另一个抛出first键不匹配)。
如果性能至关重要,那么您可以通过消除不必要的键下标查找来编写它以使其运行速度更快,如下所示:
func lookUp<T:Equatable>(key:T , dictionary:[T:T]) -> T? {
for (k,v) in dictionary where k == key {
return v
}
return nil
}
and
func lookUpThrows<T:Equatable>(key:T , dictionary:[T:T]) throws -> T {
for (k,v) in dic where k == key {
return v
}
throw lookUpErrors.noSuchKeyInDictionary
}
如果您在紧密循环中使用有效值对这两者进行基准测试,则它们的性能相同。如果您使用无效值对它们进行基准测试,则可选版本的执行速度大约是两倍,因此可能实际抛出会产生一点开销。但可能没有什么值得注意的,除非你真的在一个非常紧密的循环中调用这个函数并预计会出现很多失败。
哪个更安全?
它们都同样安全。在这两种情况下,您都不能调用该函数,然后意外地使用无效结果。编译器强制您要么解开可选内容,要么捕获错误。
在这两种情况下,您都可以绕过安全检查:
// force-unwrap the optional
let name = lookUp( "JO", dictionary: dict)!
// force-ignore the throw
let name = try! lookUpThrows("JO" , dic:dict)
这实际上取决于强制调用者处理可能的失败的哪种方式更可取。
推荐哪个功能?
虽然这比较主观,但我认为答案很明确。你应该使用可选的而不是投掷的。
对于语言风格的指导,我们只需要查看标准库即可。字典已经有一个基于键的查找(该函数复制它),并且它返回一个可选值。
可选是更好的选择的一个重要原因是,在这个函数中,只有one可能出错的事情。什么时候nil
返回,这只有一个原因,那就是该键不存在于字典中。在任何情况下,函数都不需要指示它抛出的是几个原因中的哪一个,以及原因nil
返回的内容对于调用者来说应该是完全显而易见的。
另一方面,如果有多种原因,并且函数可能需要返回解释(例如,执行网络调用的函数,可能会因网络故障或数据损坏而失败),则错误分类失败并可能包含一些错误文本将是更好的选择。
在这种情况下可选更好的另一个原因是失败甚至可能是预期的/常见的。错误更多的是异常/意外的故障。返回可选值的好处是很容易使用其他可选功能来处理它 - 例如可选链接(lookUp("JO", dic:dict)?.uppercaseString
) 或默认使用 nil-coalescing (lookUp("JO", dic:dict) ?? "Team not found"
)。相比之下,try/catch
设置和使用有点痛苦,除非调用者真的想要“异常”的错误处理,即要做一堆事情,其中一些可能会失败,但想要在底部收集失败处理。