可选函数与抛出函数

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(使用前将#替换为@)

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

  • AWS Cognito / 从子节点获取用户信息

    我有一个使用 AWS Cognito AWSMobileClient 的工作 iOS 应用程序 用户可以使用 AWSAuthUI 登录和登录 注销 接下来我想做的是 拥有另一个用户的子 例如 7y873ff7 u9h4k 我想从其他用户那里
  • 使用 swift 自动滚动 UITextView (IOS 应用程序)

    我似乎无法找到自动滚动的正确解决方案UITextView using Swift 对于我的应用程序 我从 BT 接收持续数据 并且我正在更新它UITextView 然而 当UITextView将到达最新更新的行 我将不得不手动滚动 我想要实
  • Swift:覆盖子类内的类型别名

    所以我正在考虑在我的项目中使用自定义模式 但我无法让它发挥作用 主要思想是改变typealias在每个子类上访问子类特定的接口 protocol InstanceInterface class typealias Interface var
  • 在 Swift 3 中,当结果变得过高时如何计算阶乘? [复制]

    这个问题在这里已经有答案了 我编写了这个函数来返回给定数字的阶乘 func factorial n Int gt Int if n 0 return 1 else return n factorial n 1 print factorial
  • 取消所有操作+AFNetworking 3.0

    我创建了一个继承自 AFURLSessionManager 的 HTTPServiceProvider 类 添加以下代码来获取数据 let configuration NSURLSessionConfiguration defaultSes
  • 使用 Swift 使用 SOAP Web 服务

    我期望从 w3schools com 返回 XML SOAP 响应 http www w3schools com webservices tempconvert asmx http wwww w3schools com webservice
  • 为什么 UICollectionView didSelect 方法不起作用?

    我已经创建了我的UICollectionView以编程方式 在这种情况下我的didSelectItemAtIndexPath方法根本不调用 let collectionView UICollectionView frame CGRect x
  • 在 Swift 中寻找“退出”等价物[重复]

    这个问题在这里已经有答案了 我尝试把exit 0 在一个小型测试 命令行 程序中 Xcode 给出了一条错误消息 指出Use of unresolved identifier exit 这让我很困惑 因为这个问题 https stackov
  • 如何在导航栏中添加右键?

    我有一个问题要在导航栏中添加右键 我有两个视图 视图 A 和视图 B 我添加了一个导航栏来查看A 之后我使用了self navigationController pushViewController显示视图 B 视图B的导航栏左侧自动显示一
  • 在 Swift 中获取 UIImage 的主颜色

    我正在尝试在 Swift 中获取 UIImage 的主颜色 并尝试移植这段代码 https stackoverflow com questions 13694618 objective c getting least used and mo
  • Swift - 本地通知不会被触发

    我正在 Swift 3 中编码 我只是想发送通知now没有任何延迟或间隔 然而 通知永远不会被触发 这是我的代码 视图控制器代码 import UserNotifications class HomeViewController UIVie
  • Swift 中的柯里化,未来会有新的声明语法吗?

    今天刚在 Linux 上安装了 Swift 来看看 尝试一个柯里化的小例子会导致警告 柯里化的语法将来会改变 但是我找不到任何关于这个新语法的信息 我尝试过的柯里化示例 func do stuff x Int y Int z Int gt
  • iOS8 CoreData“使用未实现的初始化程序”

    我尝试运行我的应用程序时收到以下错误 致命错误 对类 rcresttest CatalogItem 使用未实现的初始化程序 init entity insertIntoManagedObjectContext 我可以通过将数据模型中的实体类
  • 确定 SceneKit 中 SKVideoNode 的视频大小/长宽比

    如何从 AVPlayer 获取视频的视频大小来设置节点的几何大小 例如 我有一个具有宽度和高度的 SCNPlane let planeGeo SCNPlane width 5 height 5 所以现在我实例化我的视频播放器 let vid
  • 从“NSPercientStoreResult”转换为不相关类型“Entity”总是失败

    我正在创建一个小应用程序来学习 CoreData 中的多对多关系 但是 使用下面的代码 从 NSFetchResult 到实体类 Groepering 的转换出现错误 与我的项目相比 我在互联网上找到的示例没有看到任何差异 为什么转换仍然失
  • 如何使用AudioKit保存音频文件?

    我有音频文件 我给它做了一些效果 let pitchshifter AKPitchShifter self audioPlayer pitchshifter shift 10 AudioKit output pitchshifter 如果我
  • 如何接收有关与我共享的记录中所做更改的 CloudKit 通知?

    我有两个 iCloud 帐户 A and B 在两个不同的设备上 来自其中之一 A 我将 ckrecord 分享给另一个人 B 像这样 let controller UICloudSharingController controller p
  • UIButton的高亮状态由什么控制事件开始和结束

    我正在创建类似钢琴的视图UIButton作为钢琴键 什么UIControlEvents当按钮获得和失去突出显示状态时 我应该监听以获得回调吗 我试图创建子类UIButton并添加属性观察者highlighted并且运行良好 然而 有时我需要
  • 减少 CoreData 的调试输出?

    我正在开发一个使用 CoreData 的 iOS macOS 项目 它工作正常 但它会向控制台输出大量调试信息 这使得控制台无法使用 因为我的打印语句隐藏在所有与 CoreData 相关的内容中 我有一个非常简单的 CoreData 设置
  • Swift 中的 import 语句是否有相关成本?

    阅读字符串宣言 我看到一个段落 https github com apple swift blob master docs StringManifesto md batteries included关于避免Foundation不需要的时候导

随机推荐

  • 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