可选函数与抛出函数

2024-05-05

考虑我编写的以下查找函数,该函数使用可选值和可选绑定,如果在字典中找不到键则报告一条消息

func lookUp<T:Equatable>(key:T , dictionary:[T:T]) -> T? {
    for i in dictionary.keys {
       if i == key{
           return dictionary[i]
       }
    }
    return nil
}

let dict = ["JO":"Jordan",
   "UAE":"United Arab Emirates",
   "USA":"United States Of America"
]

if let a = lookUp( "JO",dictionary:dict ) {
    print(a) // prints Jordan 
} else {
    print("cant find value")
}

我重写了以下代码,但这一次,使用错误处理、保护语句、删除-> T?并编写一个符合以下条件的枚举ErrorType:

enum lookUpErrors : ErrorType {
    case noSuchKeyInDictionary
}

func lookUpThrows<T:Equatable>(key:T , dic:[T:T])throws {
    for i in dic.keys{
        guard i == key else {
            throw lookUpErrors.noSuchKeyInDictionary
        }
        print(dic[i]!)   
    }
}

do {
    try lookUpThrows("UAE" , dic:dict) // prints united arab emirates
}
catch lookUpErrors.noSuchKeyInDictionary{
    print("cant find value")
}

这两个功能都运行良好,但是:

  • 哪个函数可以提供更好的性能

  • 哪个功能“更安全”

  • 推荐哪个功能(基于优缺点)


表现

这两种方法应该具有相当的性能。在底层,它们都在做非常相似的事情:返回一个带有已检查标志的值,并且只有当标志显示结果有效时,才会继续。对于选项,该标志是枚举(.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设置和使用有点痛苦,除非调用者真的想要“异常”的错误处理,即要做一堆事情,其中​​一些可能会失败,但想要在底部收集失败处理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可选函数与抛出函数 的相关文章

  • let/var 如何解决可变性? [复制]

    这个问题在这里已经有答案了 我没有任何问题 我只是想对有关可变性的问题进行一些澄清 在 Objective C 中我们会使用例如NSMutableArray得到一个可变数组和NSArray得到一个不可变的 我对两者的内部运作了解不多 但据我
  • iOS 13 检查 CLLocationManager 的临时授权状态

    根据 WWDC 视频 https developer apple com videos play wwdc2019 705 https developer apple com videos play wwdc2019 705 当你要求 Al
  • UITesting、XCTest 当前 ViewController 类

    简单的问题 我有一个按钮可以执行到下一个视图控制器的操作 我想写 UI XCTest 来告诉我它是否打开了我想要的视图控制器 UI 测试框架无法访问您的应用程序代码 这使得无法对实例进行类断言 你不能够directly告诉屏幕上的控制器的类
  • 在 UITableViewController 中重新排序行后 UI 更新不正确

    因此 我对表中的行重新排序 用户界面最终结果不正确 场景如下 表内容原文 a b c d e 如果我移动第 0 行 当前a 到第 4 行 当前e 我看到的最终结果是 c d e a a 一些背景 该表正在读取 Realm 对象的列表 我确认
  • UILabel 中的文本未垂直居中

    我使用以下代码创建了一个标签 func setupValueLabel valueLabel numberOfLines 1 valueLabel font UIFont name Avenir Black size 50 valueLab
  • XCode 7 中的 AWSS3TransferManagerUploadRequest

    我今天升级到 Xcode 7 Swift 2 0 我的项目正在使用 CocoaPods 我正在 POD 文件中导入所有与 AWS 相关的文件 我已经设置了桥接标头 并导入了 Amazon 告诉我的所有文件 在升级到 Swift 2 0 之前
  • 在 UITableView 的部分标题文本下方添加一些边距

    我已经设计了标题文本的样式 func tableView tableView UITableView cellForRowAtIndexPath indexPath NSIndexPath gt UITableViewCell let ce
  • 如何在 Swift 中使用未知密钥解码 JSON 响应?

    我想将数据拆分为https blockchain info ticker https blockchain info ticker这样每一行都是它自己的String在一个数组中 我正在制作一个获取所选货币价格的应用程序 因此 如果有人想要澳
  • 具有动态警报正文的快速本地通知

    所以我可以创建一个像这样的本地通知 var localNotification UILocalNotification localNotification fireDate NSDate timeIntervalSinceNow 7 loc
  • 我们能否检测用户是否通过主页按钮或锁定按钮离开而没有监听 darwin 通知?

    我最近向应用程序商店提交了一个新的二进制文件并将其发送以供审核 但它立即被拒绝并显示以下消息 不支持的操作 不允许应用程序监听设备锁定通知 经过一番挖掘后 我发现我们无法使用 com apple springboard lockstate
  • iOS 防止计时器 UILabel 在数字变化时“晃动”

    我有一个UILabel它以以下格式显示计时器的输出MM ss SS 分 秒 厘秒 但是随着厘秒宽度的变化 它从左向右 摇动 例如 11 比 33 窄 有什么办法可以减轻这种情况吗 我尝试过将其居中 给它固定的宽度 但它们似乎没有帮助 从iO
  • iOS 电池监控 Swift

    我已将监控设置为启用 但模拟器和设备中的电池电量仍然为 1 UIDevice currentDevice batteryMonitoringEnabled true var level UIDevice currentDevice batt
  • 如何使用完成处理程序等待 firestore 请求的完成

    我正在慢慢地了解完成处理程序 如果我有一个 firestore 查询 如果我想使用完成处理程序 则有点向后工作 当 firestore 查询完成时 我必须使用completion 但它的设置功能仍然让我感到困惑 因此 如果这是一个将闭包作为
  • SwiftUI:状态栏颜色

    有没有办法将 SwiftUI 视图的状态栏更改为白色 我可能错过了一些简单的东西 但我似乎找不到在 SwiftUI 中将状态栏更改为白色的方法 到目前为止我只看到 statusBar hidden Bool 状态栏文本 色调 前景色可以通过
  • 检测 AVAudioPlayer 中的播放结束

    我有几个短的 mp3 声音 我将它们存储在数组中 并希望连续播放它们 有什么方法可以检测 AVAudioPlayer 何时停止播放 以便我可以调用完成处理程序并播放下一个声音 我知道有一个委托 但我正在使用 Playground 和 SKS
  • 在 SwiftUI 中使用分段式选取器在两个页面之间滑动

    我有一个Picker with pickerStyle SegmentedPickerStyle 使其成为分段控件 我想让页面在之间平滑滑动 而不是使用条件语句替换视图 这是我迄今为止所做的 gif 这是到目前为止的代码 由if 而不是在不
  • 当 UITextField 已满或空时显示警报 Swift

    下面的代码中 如果 userNameTF 或 passwordTF 已满或为空 则会显示警报 IBAction func LoginBtn sender AnyObject let userName userNameTF text let
  • 为什么我不能在 Realm 属性上使用 private

    我正在尝试在 RealmSwift 中存储一个枚举案例 但 Realm 不支持枚举 本文 https medium com it works locally persisting swift enumerations with realm
  • iOS 中的构建对象文件扩展名是什么?

    当我在项目中构建java对象类时 将创建带有 class扩展名的构建文件 并且人类不可读 快速构建文件怎么样 example car java gt build gt car class 构建后会是什么 car swift gt build
  • IPV6 快速可达性

    我是 swift 和 xcode 的新手 并且我的应用程序因 IPV6 而被拒绝 性能 2 1 当我们执行以下操作时 您的应用程序会在运行 iOS 9 3 5 并连接到 IPv6 网络的 iPad 和 iPhone 上崩溃 具体来说 当我们

随机推荐

  • jQuery Deferred - 向 Deferred 合约添加回调

    我正在尝试在现有 Deferred 的状态设置为成功之前向其合约添加另一个异步调用 不要尝试用英语解释这一点 请参阅以下伪代码 when ajax url someUrl data data async true success funct
  • 用于电子邮件和文件日志记录的 Symfony2 Monolog 设置

    我想设置 Symfony2 向我发送电子邮件critical错误 但只需记录error级别错误 下面的设置可以做到这一点吗 monolog handlers main type fingers crossed action level er
  • 如何使用 swift flatMap 从数组中过滤掉选项

    我对 flatMap 有点困惑 添加到 Swift 1 2 假设我有一些可选类型的数组 例如 let possibles Int nil 1 2 3 nil nil 4 5 在 Swift 1 1 中 我会做一个过滤器 然后是一个像这样的地
  • 如何用 Scala 编写毕达哥拉斯定理?

    直角三角形斜边的平方等于另外两条边的平方和 这就是毕达哥拉斯定理 根据斜边长度 a 和 b 计算斜边的函数将返回 sqrt a a b b 问题是 您如何在 Scala 中定义这样一个函数 使其可以与实现适当方法的任何类型一起使用 对于上下
  • 编写代码以:启动 R 会话、运行 R 脚本、终止会话、重复

    我正在寻找一种简单的 设置后就忘记它 的方式 无论是作为终端中的单个参数字符串还是简单的 Java 程序 来自动执行以下操作 1 启动R会话 2 告诉 R 源 R 文件包含冗长的并行模拟代码 3 完成后终止R会话 4 开始一个新的R会话 5
  • VB6 - Lua 集成

    我想知道是否有人有任何集成 Lua 和 VB6 的技巧 我正在运行一个小型在线角色扮演游戏 添加一些脚本会很棒 嗯 这是可行的 我曾经为 Lua 5 0 2 做过 但找不到文件 在您拥有的选项中 您可以 将 Lua 封装在公开 Lua AP
  • MySQL/Postgres查询5分钟间隔数据

    我需要查询方面的帮助 假设这是表中的数据 timestamp 2010 11 16 10 30 00 2010 11 16 10 37 00 2010 11 16 10 40 00 2010 11 16 10 45 00 2010 11 1
  • 在 WatchKit 和主机 App 中使用具有不同标志的同一文件

    我试图在我的 watchkit 扩展和主机应用程序中使用相同的代码 但在主机应用程序中使用一些附加代码 在 watchkit 扩展中使用一些附加代码 为此 我在各自的目标上添加了 WATCH 和 APP swift 标志 问题是 当我在选择
  • Socket.io 不断重复连接并忽略其他事件

    我正在尝试制作一个网络应用程序 用户可以在其中互相玩环形国际象棋 这是我的 app js 在服务器上 var express require express var app express var http require http Ser
  • 仅使用特定提交消息触发 travis CI 构建

    我希望 travis 仅在我有特定的提交消息时才启动 我怎样才能做到这一点 我的 travis yml 文件是here https github com mosaadm mooltipass blob master travis yml 我
  • 如果表单脏则阻止路由 [ Angular 2 ]

    我被这个挡住了在 Angular 2 中 我需要阻止任何用户单击事件 甚至浏览器刷新 如果页面中的表单为dirty 你能帮我出出主意吗 看来您正在寻找可以停用 https angular io docs ts latest guide ro
  • 当我将 HTML 标签设置为 100% 高度时,我的内容消失了

    我有一个垂直布局 我想保持页面居中 一列保持固定在页面上 而另一列应根据内容滚动 并且有一些绝对的装饰性浮动 div 我希望滚动列垂直显示 100 即使内容不需要高度 但我似乎无法让它工作 我已将 html 标签和 body 标签以及所有必
  • 列表框显示类名称而不是值

    我正在开发一个项目 其中用户应该向动物输入值 名称 年龄 性别等 并且用户输入的值应该显示在列表框中 这些类相互继承 以下是继承的工作原理 Animalclass 是所有类的父类 Mammal类继承自Animal class Dog类继承自
  • 从循环中删除重复项

    我有以下代码 for i in 0 sold length 1 duplicate sold i print duplicate check duplicates print print sold i lotnumber t print s
  • iframe可以弹出Lightbox风格的盒子吗?

    这个问题不是关于在 Lightbox 中弹出 iframe 的问题 而是关于在 Lightbox 中弹出 iframe 的问题 相反 它是关于页面上的 iframe 它可以在页面中启动自己的 Lightbox 样式框contains那个 i
  • Microsoft 开源 .NET 后 CoreCLR 与 Mono 项目的关系

    有人可以向我解释一下 Mono 和 Microsoft 最近提供的开源 Linux 可移植 NET 堆栈 CoreCLR CoreFX Roslyn ASP NET 之间当前的关系吗 很明显这些项目是重叠的 所以我很好奇它们两个的路线图是什
  • 尝试在iPhone上生成随机数,得到相同的数字[重复]

    这个问题在这里已经有答案了 我正在尝试制作一款纸牌游戏 我正在使用以下代码来绘制随机卡 iCard 随机 55 但 icard 总是以 28 开头 似乎它以相同的顺序返回数字 有没有办法在每次第一次调用该函数时获得不同的随机数 random
  • 在mysql查询中对多个日期范围求和

    我有一个 MySql 表 产品 包含三列 Date Product Qty 我的目标是每周对每种产品的数量进行求和 获取两个给定日期之间的 SUM 很容易 SELECT SUM qty FROM products WHERE date gt
  • 创建 .ICS 文件,添加到 Outlook

    我正在创建一个简单的应用程序 允许用户下载 ICS 文件 并将其导入到他们选择的日历应用程序 站点中 我对创建过程感到满意 但对在 Outlook 中打开它们有疑问 将使用C ASP NET进行开发 当我打开一个日历时 它会添加一个新日历
  • 可选函数与抛出函数

    考虑我编写的以下查找函数 该函数使用可选值和可选绑定 如果在字典中找不到键则报告一条消息 func lookUp