避免处理所有异常,直到它们到达全局处理程序
Posted
技术标签:
【中文标题】避免处理所有异常,直到它们到达全局处理程序【英文标题】:Avoid handling all exceptions until they've reached a global handler 【发布时间】:2016-11-02 16:17:53 【问题描述】:如果我调用hello.f
,编译器会强制我处理所有抛出的异常。我可以使用try?
吞下它们,或者通过不指定要捕获然后重新抛出的异常类型来添加catch
all。但是,如果我执行后者,我需要将调用函数标记为 throws,并且该过程一直继续向上堆栈。
是否可以忽略f
的异常,使其最终成为可以全局处理的未处理异常?
enum e : Error
case hello
case world
class hello
func f() throws
throw e.hello
【问题讨论】:
rethrows
似乎不在语言指南中。
那超出了我的范围,我没有写语言指南。 :)
你的标题是“避免处理所有异常”。请澄清你的意思。 “全球处理”是什么意思?
我认为你不能。这是设计使然。 Swift 对错误处理更加严格。
@IanWarburton,是的,我修改了我在评论中快速编写的代码,这不是正确的语法,顺便说一句,但你可以去func g() throws try f()
这个,现在是正确的,在这种情况下,您只需转发错误而不在本地处理它。
【参考方案1】:
是否可以忽略 f 的异常,最终成为可以全局处理的未处理异常?
总之,没有。 Swift 错误处理设计的全部要点是您必须明确承认每个阶段都可能出现错误。
在我看来,你在思考 Objective-C 如何处理 NSException,但 Swift 不是这样的(而且 Error 也不像 NSException)。
【讨论】:
来自 C#...我认为 Anders Hejlsberg 在这里提出了一个很好的论据...artima.com/intv/handcuffs.html。 为什么不能使用rethrows
?然后,您只需将责任传递给链中的前一个调用者。这不是 OP 想要的吗?
其实我应该说的是throws
,而不是rethrows
。
@rmaddy 绝对,但这不是“忽略”。正如我所说,它正在承认。当然,我可能不明白 Ian 想要什么,但我认为他想在每个阶段不说 throw
/ try
,没错,你不能那样做。
@rmaddy 当然。但我认为 Ian 的意思确实是“忽略”。因为这就是例如响应者链的工作原理,以及 NSException 处理在 Objective-C 中的工作方式:运行时只是不断地沿着调用链 寻找 寻找 someone 来处理这件事。 (但我的观点是,Swift 错误处理不是这样的:你必须在调用链的每一步都以某种方式处理它。【参考方案2】:
根据您的期望,我创建了这个示例:
enum PetError : Error
case pet
class Pet
func pet() throws
throw PetError.pet
class Cat
func cat() throws
let pet = Pet()
try pet.pet()
class Tiger
func tiger() throws
let cat = Cat()
try cat.cat()
然后您可以在您需要的***别处理PetError
异常 (=errors),而在链内,错误只是转发到上层。
let tiger = Tiger()
do
try tiger.tiger()
catch PetError.pet
print("PetError.pet")
注意:当然,您可能希望在一天结束时处理所有异常(=错误),但这不是这个小示例的一部分。
【讨论】:
【参考方案3】:这就是我所追求的。输出是“你好\n”。感谢问题的cmets中的holex。
enum e : Error
case hello
case world
class hello
func f() throws
throw e.world
class goodbye
func g() throws
let h = hello()
try h.f()
class world
func w() throws
let g = goodbye()
try g.g()
let w = world()
do
try w.w()
catch e.world
print("hello")
【讨论】:
@holex 我想与世界分享更多我的命名约定。如果你回答,我会给你积分。 @IanWarburton 说到命名约定,类型名称应该是UpperCamelCase
,例如Hello
、Goodbye
、World
和E
。
不过,我确实认为你只是在证明我说的是对的。你必须在你知道错误可以通过这种方式传递的链的每个阶段明确地显示编译器。
@IanWarburton,好的,我已经根据您的代码发布了答案;我实际上并不想要额外的功劳,但我绝对反对你在 Swift 中的命名约定。
@holex 可以说这不是惯例。以上是关于避免处理所有异常,直到它们到达全局处理程序的主要内容,如果未能解决你的问题,请参考以下文章
Springboot的Filter,HandlerInterceptor,Aspect与异常处理
SpringBoot2.0系列教程Springboot框架添加全局异常处理