Swift 枚举if-else比较

Swift 枚举if-else比较,swift,if-statement,enums,Swift,If Statement,Enums,如何在以下代码中执行正确的比较检查 enum Location { case ontop case inside case underneath } struct Item { var location: Location? func checkStuff(currentLocation: Location?) { if case .ontop = currentLocation { // DO SOME STU

如何在以下代码中执行正确的比较检查

enum Location {
    case ontop
    case inside
    case underneath
}

struct Item {
    var location: Location?

    func checkStuff(currentLocation: Location?) {
        if case .ontop = currentLocation {
            // DO SOME STUFF
        }
    }
}

// currentLocation is optional, and initially nil
var currentLocation: Location?

var item1 = Item(location: .ontop)
item1.checkStuff(currentLocation: currentLocation)

currentLocation = item1.location

var item2 = Item(location: .inside)
item2.checkStuff(currentLocation: currentLocation)
因此有一个结构,它的1个属性是enum
Location
,因此它只能有3个值中的1个

如果实例的
location
属性与外部提供的同一类型的值(即位置的当前状态)(来自同一对象类型的另一个实例)相同,则该结构有一个方法可以执行操作

我无法获得正确的语法以进入
if
语句的正确部分

我还尝试了展开可选的
currentLocation

if let tempCurrentLocation = currentLocation {
     if case tempCurrentLocation = Location.ontop {
          print("Currently ontop")
          location = .ontop
     } else {
          print("Currently NOT ontop")
          location = .inside
     }
} else {
     print("Not able to unwrap enum...")
}

需要注意的是,
currentLocation
不是
位置
,而是
位置
(也称为
可选
)。因此,您必须首先针对
可选
的情况进行模式匹配,而不是针对
位置
的情况。然后,在
可选
的案例模式中,您可以匹配
位置
的各种案例

以下是句法糖分的进展,从最冗长的开始,到最简洁、最常用的方法:

  • 如果大小写可选.some(.ontop)=当前位置{…}
  • 如果case.some(.ontop)=当前位置{…}
  • 最后是首选方式:
    if case.ontop?=当前位置{…}
if case
只有在您想要检查大量案例中的一小部分时才是真正理想的。如果需要检查多个案例,最好使用
开关
。案例模式相同:

switch currentLocation {
    case .onTop?: // ...
    case .inside?: // ...
    case .underneath?: // ...
    case nil: // ...
}

尝试使用
开关
语句:

switch self.currentLocation {
case .ontop?:
    break
case .inside?:
    break
case .underneath?:
    break
case nil:
    // In this case, `self.currentLocation` is `nil` rather than one of the cases of `Location`
    break
}

在switch语句中的每个case之后都需要有一个
,因为
self.currentLocation
是一个
位置?
。开关箱中的值必须与
self.currentLocation
的类型匹配。通过简单地编写
.ontop
.inside
等,它们的类型将是
位置
,而编写
.ontop?
.inside?
等,它们的类型将是
位置
,这是正确的类型。

您可以像这样优雅地编写它,最好使用
switch
语句,而不是
if
条件

enum Location {
    case ontop
    case inside
    case underneath
}

struct Item {
    var location: Location?

    func checkStuff(currentLocation: Location?) {
        switch currentLocation {
        case .ontop?:
            print("on top")
        case .inside?:
            print("inside")
        case .underneath?:
            print("underneath")

        case .none:
            print("Location is nil")
        }
    }
}

如果要使用
位置?
参数进行单个
If
测试,可以添加

func checkStuff(currentLocation: Location?) {
    if case .ontop? = currentLocation {
        // DO SOME STUFF
    }
}
或者只需使用
==
测试(可用于将可选项与文字进行比较):

我认为后一种方法会产生更自然的代码,但是如果枚举有关联的值(它没有),那么
if case
方法确实很有价值

显然,如果您想要测试其他
位置
枚举可能性,那么您应该使用
开关
语句(在各种情况之后再次使用
),正如其他人所建议的:

func checkStuff(currentLocation: Location?) {
    switch currentLocation {
    case .ontop?:
        // DO SOME STUFF IF ONTOP
    case .inside?:
        // DO SOME OTHER STUFF IF INSIDE
    case .underneath?:
        // DO YET SOME OTHER STUFF IF UNDERNEATH
    case nil:
        // DO YET SOME OTHER STUFF IF NIL
    }
}

只需
切换
枚举位置出于好奇,您提供了展开的尝试。虽然这是不必要的,但它应该有效。我们是否应该从你的评论中推断出它出于某种原因不起作用?就我个人而言,如果我使用
if case
我认为
if case tempCurrentLocation=Location.ontop{…}
是令人困惑的,我会使用
if case.ontop=tempCurrentLocation{…}
来代替,但您的构造似乎是可行的。不管怎样,正如下面所讨论的,还有一些更优雅的模式不需要这个展开步骤。可能相关的是,虽然它们对解释很有用,
是可选的。一些(.foo)
。一些(.foo)
模式很少使用,开发人员几乎在所有情况下都喜欢使用
.foo?
。是的,我要强调这一点。@Rob是的,说得好。我试图展示案例语法的直接问题,OP正在尝试。@Alexander谢谢你的答案和解释-我用了你的
if case.ontop?=语法,并按预期工作@罗布也感谢你的指针——它看起来很简单,我不敢相信我没有试过!我也会重新测试。最好直接匹配
开关中的可选项。这样,你就可以像处理其他案件一样处理
nil
。@Biju谢谢你的回复。这是一个很好的结构。我希望在检查时定期使用
开关
。然而,在这种特殊情况下,我只检查此属性是否设置为可用值中的1(
.ontop
)@Alexander,再次感谢您提醒我们有关
可选

func checkStuff(currentLocation: Location?) {
    switch currentLocation {
    case .ontop?:
        // DO SOME STUFF IF ONTOP
    case .inside?:
        // DO SOME OTHER STUFF IF INSIDE
    case .underneath?:
        // DO YET SOME OTHER STUFF IF UNDERNEATH
    case nil:
        // DO YET SOME OTHER STUFF IF NIL
    }
}