有没有办法将变量绑定到switch语句中的多个备选项?

时间:2014-06-02 23:20:25

标签: swift

假设我有一个枚举定义如下:

enum Response {
    case Result(String, Int)
    case Error(String)
}

然后,我得到了这样的答复:

let resp: Response = // ...

假设我想编写一个switch语句并以与Result和Error案例相同的方式处理,并将同名的变量绑定到它们包含的String。我怎样才能做到这一点?从概念上讲,类似于此:

switch resp {
    case let .Result(str, _), let .Error(str):
        println("Found: \(str)")
}

其中str绑定两次,_表示我对Int携带的Result值不感兴趣。

到目前为止,我能找到的最接近的事情是声明一个这样的内联函数,然后调用它:

func processRespString(str: String) {
    println("Found \(str)")
}

switch resp {
    case let .Result(str, _): processRespString(str)
    case let .Error(str): processRespString(str)
}

有更好的方法吗?

3 个答案:

答案 0 :(得分:3)

已被接受的Swift evolution Proposal SE-0043使用Swift 3解决了此问题。

enum Response {
    case result(String, Int)
    case error(String)
}

let resp = Response.error("Some text")

switch resp {
case let .result(str, _), let .error(str):
    print("Found: \(str)") // prints Found: Some text
}

使用Swift 2,之前的Playground代码会生成错误:case labels with multiple patterns cannot declare variables。但是,使用Swift 3,它不会产生任何错误并且具有预期的行为。

答案 1 :(得分:2)

不,但是如果你想访问Response的String值,无论它是.Result还是.Error,你都可以这样做:

enum Response {
    case Result(String, Int)
    case Error(String)

    func Message() -> String {
        switch self {
            case let .Result(str, _):
                return str
            case let .Error(str):
                return str
        }
    }
}

var resp: Response = .Error("Fault")
resp = .Result("Success",5)

println(resp.Message())

这样你就可以将枚举的逻辑保留在枚举本身内。

答案 2 :(得分:1)

最明显的方法是使用可选代替枚举来表示错误:

struct Response {
    var string:String
    var result: Int?
    var isError: Bool { return result == nil }
}

如果您坚持使用枚举,可以将其与原始代码混合使用 -

// Auxiliary enum
enum IntResponse {
    case Result(Int)
    case Error()
}

struct FullResponse {

    // Real properties 
    var string: String
    var response: IntResponse

    // Convenience property
    var result: Int? { 
        switch(response) {
            case let .Result(value): return value
            case let .Error(): return nil
        }
    }

    // Initializers for success and error
    init(errorString:String) {
        self.string = errorString
        self.response = IntResponse.Error()
    }
    init(string:String, result:Int) {
        self.string = string
        self.response = IntResponse.Result(result)
    }
}

// An example usage

let error = FullResponse(errorString: "some error")
let success = FullResponse(string: "success", result: 10)

func do_something(response: FullResponse) {
    println(response.string)  // works for any of the cases
}