Swift 检查是否可以从开关中的参数创建枚举

Swift 检查是否可以从开关中的参数创建枚举,swift,enums,switch-statement,Swift,Enums,Switch Statement,我有一个类似于 enum MyEnum { case a(Foo) case b case c(Bar) enum Foo: String { case one case two } enum Bar: String { case three case four } } 我正在尝试为此创建一个可失败的初始化器函数,以便您可以像 MyEnum(base: "a", para

我有一个类似于

enum MyEnum {
    case a(Foo)
    case b
    case c(Bar)

    enum Foo: String {
        case one
        case two
    }

    enum Bar: String {
        case three
        case four
    }
}
我正在尝试为此创建一个可失败的初始化器函数,以便您可以像

MyEnum(base: "a", parameter: "one")

我让它像这样工作(但很笨重)

init?(base: String, parameter: String?) {
    switch (base, parameter) {
    case ("a", let p?) where Foo(rawValue: p) != nil:
        self = .a(Foo(rawValue: p)!)
    case ("b", _):
        self = .b
    case ("c", let p?) where Bar(rawValue: p) != nil:
        self = .c(Bar(rawValue: p)!)
    default:
        return nil
    }
}
这将打开
base
,然后在输入案例之前检查是否可以创建下一个值

但是,我现在必须创建两次
Foo
Bar
,然后强制展开第二个


有没有办法让开关盒创建
Foo
Bar
,并且只在可以创建的情况下输入开关盒,这样我就可以使用创建的开关盒,而不必创建第二个开关盒?

不要太复杂。打开
base
值,并在需要时使用
if
guard
和可选绑定处理
参数

init?(base: String, parameter: String?) {
    switch base {
    case "a":
        guard let p = parameter, let foo = Foo(rawValue: p) else { return nil }
        self = .a(foo)
    case "b":
        self = .b
    case "c":
        guard let p = parameter, let bar = Bar(rawValue: p) else { return nil }
        self = .c(bar)
    default:
        return nil
    }
}
易于理解,无需强制展开,
Foo
Bar
值仅创建一次(如果需要)


它还最小化了测试:例如,
MyEnum(base:“a”,参数:nil)
将转到
“a”
案例并返回
nil
。在switch语句中,它将无法匹配
(“a”,让p?
大小写,然后仍然检查其余的大小写。

另一种选择是
切换
两个
Foo
Bar
初始值设定项:

init?(base: String, parameter: String?) {
    switch (base, parameter.flatMap { Foo.init(rawValue: $0) ?? Bar(rawValue: $0) } as Any?) {
    case ("a", let foo as Foo):
        self = .a(foo)
    case ("b", _):
        self = .b
    case ("c", let bar as Bar):
        self = .c(bar)
    default:
        return nil
    }
}

缺点是,如果
Foo
Bar
有共同的情况,那么您可能无法得到想要的结果。另外,如果案例数量增加,那么
开关上的表达式也可能会增加

你在开关中有两次
“a”
,是打字错误吗?@RobertDresler,~~这些案例有不同的
,其中
谓词,它们不一样。~~哦,等等,第二个应该是“c”。不要把它弄得太复杂。打开
base
,如果让p=parameter,让foo=foo(rawValue:p)
(或
guard-let…
)。或者跳过
Switch
语句,只使用
if
语句:
如果base==a,让p=parameter,让foo=foo(rawValue:p)
,在temp
p
变量中没有必要,只要
让foo/bar=parameter.flatMap(foo/bar.init)
就可以了。@user28434:这是另一种选择,但我觉得这更容易阅读(当然是基于观点的)。
init?(base: String, parameter: String?) {
    switch (base, parameter.flatMap { Foo.init(rawValue: $0) ?? Bar(rawValue: $0) } as Any?) {
    case ("a", let foo as Foo):
        self = .a(foo)
    case ("b", _):
        self = .b
    case ("c", let bar as Bar):
        self = .c(bar)
    default:
        return nil
    }
}