将 "or" 逻辑与多个 "if case" 语句一起使用
Use "or" logic with multiple "if case" statements
假设我有一个带有关联值的枚举案例,以及该枚举类型的两个变量:
enum MyEnum {
case foo, bar(_ prop: Int)
}
let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)
如果我想检查 两个 变量是否与一般情况与关联值匹配,我可以用逗号来做到这一点:
if case .bar = var1, case .bar = var2 {
print("both are bar")
}
但是我需要检查 either 是否匹配大小写,像这样:
if case .bar = var1 || case .bar = var2 {
print("at least one is bar")
}
但是,它无法编译。有没有另一种方法可以使逻辑正常工作?
您必须为您的枚举实施 Equatable 协议:
extension MyEnum: Equatable {}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
switch (lhs, rhs) {
case (let .bar(prop1), let .bar(prop2)):
return prop1 == prop2
case (.foo, .foo):
return true
default:
return false
}
}
那么下面的代码应该可以工作:
if var1 == .bar(1) || var2 == .bar(1) {
print("at least one is bar")
}
更新:如果你不需要检查关联值,你可以像这样进行模式匹配:
switch (var1, var2) {
case (.bar, _), (_, .bar): print("at least one is bar")
default: break
}
我的猜测是 if case
和 guard case
是语法糖,只是编译器支持的一个小功能,用于改善开发人员的体验。在第一种情况下,您使用的是连续条件,这也只是一种语言功能,用于替换 &&
运算符以使代码更具可读性。当您使用 &&
或 ||
运算符时,编译器会期望获得两个 return 布尔值的表达式。 case .bar = var1
本身并不是一个可以单独存在的表达式,在 Swift 中没有一些上下文,所以它不被视为 return 是 bool 的表达式。
总结一下:
if case
和 guard case
只是语法糖,与 if <expression>, <expression>
syntax
一起工作
&&
和 ||
只是逻辑运算符,它们基本上是一个函数,需要两边都有两个布尔参数。
要解决您的问题,请使用旧的 switch 语句。
希望对你有帮助。
我会在枚举本身上使用某种 isBar
属性,这样 "a or b" 测试仍然可读:
enum MyEnum {
case foo, bar(_ prop: Int)
var isBar: Bool {
switch self {
case .bar: return true
default: return false
}
}
}
let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)
let eitherIsBar = var1.isBar || var2.isBar
我对这类事情的解决方案是:
if [var1, var2].contains(.bar) {
很多时候我想要它的另一种方式,一个可以根据几个值过滤的变量:
if [.bar, .baz].contains(var)
但实际上,如果涉及关联值,则必须使它们相等并定义一个运算符。
假设我有一个带有关联值的枚举案例,以及该枚举类型的两个变量:
enum MyEnum {
case foo, bar(_ prop: Int)
}
let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)
如果我想检查 两个 变量是否与一般情况与关联值匹配,我可以用逗号来做到这一点:
if case .bar = var1, case .bar = var2 {
print("both are bar")
}
但是我需要检查 either 是否匹配大小写,像这样:
if case .bar = var1 || case .bar = var2 {
print("at least one is bar")
}
但是,它无法编译。有没有另一种方法可以使逻辑正常工作?
您必须为您的枚举实施 Equatable 协议:
extension MyEnum: Equatable {}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
switch (lhs, rhs) {
case (let .bar(prop1), let .bar(prop2)):
return prop1 == prop2
case (.foo, .foo):
return true
default:
return false
}
}
那么下面的代码应该可以工作:
if var1 == .bar(1) || var2 == .bar(1) {
print("at least one is bar")
}
更新:如果你不需要检查关联值,你可以像这样进行模式匹配:
switch (var1, var2) {
case (.bar, _), (_, .bar): print("at least one is bar")
default: break
}
我的猜测是 if case
和 guard case
是语法糖,只是编译器支持的一个小功能,用于改善开发人员的体验。在第一种情况下,您使用的是连续条件,这也只是一种语言功能,用于替换 &&
运算符以使代码更具可读性。当您使用 &&
或 ||
运算符时,编译器会期望获得两个 return 布尔值的表达式。 case .bar = var1
本身并不是一个可以单独存在的表达式,在 Swift 中没有一些上下文,所以它不被视为 return 是 bool 的表达式。
总结一下:
if case
和guard case
只是语法糖,与if <expression>, <expression>
syntax 一起工作
&&
和||
只是逻辑运算符,它们基本上是一个函数,需要两边都有两个布尔参数。
要解决您的问题,请使用旧的 switch 语句。 希望对你有帮助。
我会在枚举本身上使用某种 isBar
属性,这样 "a or b" 测试仍然可读:
enum MyEnum {
case foo, bar(_ prop: Int)
var isBar: Bool {
switch self {
case .bar: return true
default: return false
}
}
}
let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)
let eitherIsBar = var1.isBar || var2.isBar
我对这类事情的解决方案是:
if [var1, var2].contains(.bar) {
很多时候我想要它的另一种方式,一个可以根据几个值过滤的变量:
if [.bar, .baz].contains(var)
但实际上,如果涉及关联值,则必须使它们相等并定义一个运算符。