在Swift中,投掷和再投掷有什么区别?

在Swift中,投掷和再投掷有什么区别?,swift,error-handling,try-catch,throws,rethrow,Swift,Error Handling,Try Catch,Throws,Rethrow,在搜索了一些参考资料之后,很遗憾,我找不到关于理解throws和rethrows之间差异的有用且简单的描述。当我们试图理解应该如何使用它们时,会有点困惑 我要提到的是,我对-default-抛出的最简单的错误传播形式比较熟悉,如下所示: enum CustomError: Error { case potato case tomato } func throwCustomError(_ string: String) throws { if string.lowerca

在搜索了一些参考资料之后,很遗憾,我找不到关于理解
throws
rethrows
之间差异的有用且简单的描述。当我们试图理解应该如何使用它们时,会有点困惑

我要提到的是,我对-default-
抛出的最简单的错误传播形式比较熟悉,如下所示:

enum CustomError: Error {
    case potato
    case tomato
}

func throwCustomError(_ string: String) throws {
    if string.lowercased().trimmingCharacters(in: .whitespaces) == "potato" {
        throw CustomError.potato
    }

    if string.lowercased().trimmingCharacters(in: .whitespaces) == "tomato" {
        throw CustomError.tomato
    }
}

do {
    try throwCustomError("potato")
} catch let error as CustomError {
    switch error {
    case .potato:
        print("potatos catched") // potatos catched
    case .tomato:
        print("tomato catched")
    }
}
到目前为止还不错,但问题出现在:

func throwCustomError(function:(String) throws -> ()) throws {
    try function("throws string")
}

func rethrowCustomError(function:(String) throws -> ()) rethrows {
    try function("rethrows string")
}

rethrowCustomError { string in
    print(string) // rethrows string
}

try throwCustomError { string in
    print(string) // throws string
}
到目前为止,我所知道的是,当调用一个
抛出
的函数时,它必须由
try
来处理,而不是
rethrows
。那又怎么样?!当我们决定使用Swift手册中的
抛出
收回
时,我们应该遵循什么逻辑

检索功能和方法

可以使用
rethrows
关键字来声明函数或方法 指示仅当它的一个函数 参数抛出一个错误。这些函数和方法称为 复吸功能和复吸方法。复吸功能及其应用 方法必须至少有一个抛出函数参数

一个典型的例子是该方法:

但是如果使用抛出闭包调用
map
,那么它本身就可以抛出 并且必须使用
try
调用:

// Example 1:

let a = [1, 2, 3]

func f1(n: Int) -> Int {
    return n * n
}

let a1 = a.map(f1)
// Example 2:

let a = [1, 2, 3]
enum CustomError: Error {
    case illegalArgument
}

func f2(n: Int) throws -> Int {
    guard n >= 0 else {
        throw CustomError.illegalArgument
    }
    return n*n
}


do {
    let a2 = try a.map(f2)
} catch {
    // ...
}
  • 如果
    map
    被声明为
    throws
    而不是
    rethrows
    ,那么您将 即使在示例1中,也必须使用
    try
    调用它, 这是“不方便”和膨胀的代码不必要的
  • 如果
    map
    声明时没有
    throws/rethrows
    ,则您不能 使用抛出闭包调用它,如示例2所示
Swift标准库中的其他方法也是如此 其中包含函数参数:
filter()
索引(其中:)
forEach()
等等

就你而言

func throwCustomError(function:(String) throws -> ()) throws
表示可以抛出错误的函数,即使使用 不具说服力的论点,而

func rethrowCustomError(function:(String) throws -> ()) rethrows
表示仅在使用 提出论点

粗略地说,
rethrows
用于不抛出 错误“自行”,但仅从其功能中“转发”错误
参数

随马丁的回答再补充一点。与抛出函数具有相同签名的非抛出函数被视为抛出函数的子类型。这就是为什么当func参数也抛出时,rethrows可以确定它是哪一个,并且只需要
try
,但仍然接受不抛出的相同函数签名。当func参数抛出时,只需使用do-try块,但函数中的其他代码不会抛出错误,这是一种方便的方法。

最后一句话是金色的@亲爱的:答案的最后一句是我该如何总结。是的,那似乎更好。如果说
rethrow
s只用于闭包,而不是不需要闭包,那对吗?@Honey:我不完全明白你的意思
rethrows
仅用于具有可能抛出的函数参数的函数。如果它同时执行这两种操作,语法会是什么??
func rethrowCustomError(function:(String) throws -> ()) rethrows