【问题标题】:Swift Pattern Matching in Catch for Enum with Associated Values带有关联值的枚举的 Catch 中的 Swift 模式匹配
【发布时间】:2019-12-18 23:16:01
【问题描述】:

我想弄清楚如何对 catch 中错误类型的 enum-with-associated-value 属性进行模式匹配。使用枚举 没有 关联值时,一切都按预期工作,但我似乎无法找出这种情况的正确模式。

struct MyError: Error {
    enum Size {
        case big, small
    }

    enum Solution {
        case runAway
        case other(String)
    }

    let size: Size
    let solution: Solution
}

func action() {
    do {
        // ...
    }
    catch let error as MyError where error.size == .big {
        // This works fine, as `size` has no associated values.
    }
    catch let error as MyError where error.solution == .other {
        // I want to handle all cases of `Solution.other` here, regardless of the associated value.
    }
    catch {
       // ...
    } 
}

第二个catch 模式将无法编译(正如预期的那样,由于枚举具有关联值)。我完成此操作的通常方法是if case .runAway = error.solution {...},但将其集成到catch 模式中是个问题。

我尝试了if case/let case/case let 的多种组合,但无法在单个catch 模式匹配语句中使用。鉴于模式匹配的强大功能和灵活性,这感觉应该是可能的,所以我希望我只是忽略了一些东西。

感谢您的帮助!

【问题讨论】:

    标签: swift pattern-matching try-catch


    【解决方案1】:

    这感觉可能,但不是:/。您尝试使用的是枚举案例模式。根据here,枚举大小写模式只允许在switchifwhileguardfor 语句中使用。

    您可以在Solution 中添加isOther 属性:

    var isOther: Bool {
        if case .other = self {
            return true
        } else {
            return false
        }
    }
    

    然后在catch中使用:

    do {
        // ...
    }
    catch let error as MyError where error.size == .big {
        // ...
    }
    catch let error as MyError where error.solution.isOther {
        // ...
    }
    catch {
       // ...
    } 
    

    【讨论】:

    • 感谢您的文档参考! catch 声明中不支持此功能的确认正是我希望找到的。
    【解决方案2】:

    您的示例中应修复两件事:

    1. 比较枚举的情况应该是公平的,不是吗?对于这样一个简单的枚举,只需将Solution 标记为Equitable

    2. 不处理catch的默认情况,所以你需要添加它,例如:

      do { ... } catch let error as MyError where error.size == .big { // This works fine, assizehas no associated values. } catch let error as MyError where error.solution == .runAway { // I want to accomplish this comparison. } catch let error { ... }

    【讨论】:

    • 谢谢。符合Equatable 确实允许匹配.runAway,但仍不允许与包含关联值的.other 情况进行比较。
    • 是的,这是预期的行为,您仍然可以将案例与关联值进行比较,例如:error.solution == .other("some string"),因为将枚举标记为公平生成的默认比较函数。如果您只想比较没有关联值的案例,只需实现自定义比较功能
    • static func == (lhs: Solution, rhs: Solution) -> Bool { switch (lhs, rhs) { case (.runAway, .runAway): return true case (.other, .other): return true default: return false } } 然后添加catch let error as MyError where error.solution == .other("")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多