如何将枚举案例传递给使用“if case”检查属性案例的函数

Posted

技术标签:

【中文标题】如何将枚举案例传递给使用“if case”检查属性案例的函数【英文标题】:How to pass an enum case into a function that uses 'if case' to check for a property's case 【发布时间】:2021-04-19 18:06:08 【问题描述】:

我有一个枚举,其中每个案例都有不同(或没有)关联值。枚举不相等。

我在几个地方使用if case 来检查一个值是否属于特定情况。

enum MyEnum 
    case justACase
    case numberCase(Int)
    case stringCase(String)
    case objectCase(NonEquatableObject)


let myArray: [MyEnum] = [.justACase, .numberCase(100), .stringCase("Hello Enum"), .justACase]

if case .justACase = myArray[0] 
    print("myArray[0] is .justACase")


if case .numberCase = myArray[1] 
    print("myArray[1] is .numberCase")

但我想将它提取到它自己的方法中,然后传递我想要检查的案例。我想像下面这样。 (如果有不清楚的地方请在cmets中写出来。)

func checkCase(lhsCase: /*???*/, rhsCase: MyEnum) -> Bool 
    if case lhsCase = rhsCase 
        return true
     else 
        return false
    


// Usage:
if checkCase(lhsCase: .justACase, rhsCase: myArray[0]) 
    print("myArray[0] is .justACase")

在我上面的示例中,我假设 lhsCase 不应该是 MyEnum 类型,因为这意味着我会尝试比较两个属性(请参见下面的代码)并且需要我的枚举是可等价的。他们不是。

我不确定这是否可能。

如果以下方法可行,它也可以解决我的问题,但它没有。

if case myArray[3] = myArray[0] 
    print("myArray[0] is .justACase")

【问题讨论】:

【参考方案1】:

有一个库 CasePaths 可以做你想做的事:像这样:

struct NonEO 
    var a: Any


enum MyEnum 
    case justACase
    case numberCase(Int)
    case stringCase(String)
    case nonEO(NonEO)


let myArray: [MyEnum] = [.justACase, .nonEO(NonEO(a: 42)), .stringCase("Hello Enum"), .justACase, .nonEO(NonEO(a: "Thing"))]

func sameCase<T>(casePath: CasePath<MyEnum, T>,
                 lhs: MyEnum, rhs: MyEnum) -> Bool 
    (casePath.extract(from: lhs) != nil)
        && casePath.extract(from: rhs) != nil


sameCase(casePath: /MyEnum.justACase, lhs: myArray[0], rhs: myArray[1]) // FALSE
sameCase(casePath: /MyEnum.justACase, lhs: myArray[0], rhs: myArray[3]) // TRUE

sameCase(casePath: /MyEnum.nonEO, lhs: myArray[1], rhs: myArray[4]) // TRUE
sameCase(casePath: /MyEnum.nonEO(.init(a: 42)), lhs: myArray[1], rhs: myArray[4]) // FALSE

【讨论】:

这是一个有趣的解决方案,在查看他们在 github 上的项目时,我发现了一个指向 EnumKit 的链接(请参阅我的答案),这几乎正是我想要的。谢谢您的回答!这很有帮助! :)【参考方案2】:

Shadowrun 的answer 是一个好的开始。通过CasePaths 库,我找到了EnumKit,这部分是CasePaths 的灵感来源。然而,它提供了更简单的方法来比较案例。请参阅下面的实现。

使用这个库有一些不错的好处,它允许通过比较案例并忽略值来使具有关联值的枚举变得相等。这可能并不总是需要的,但在很多情况下会派上用场。在我的测试中,我使用它来比较 ReSwift Actions 和 Associated 值。

import Foundation
import EnumKit

class NonEquatableObject 


enum MyEnum: CaseAccessible  // <-- conform to CaseAccessible
    case justACase
    case numberCase(Int)
    case stringCase(String)
    case objectCase(NonEquatableObject)


let myArray: [MyEnum] = [.justACase, .numberCase(100), .stringCase("Hello Enum"), .justACase]

if case .justACase = myArray[0] 
    print("myArray[0] is .justACase")


if case .numberCase = myArray[1] 
    print("myArray[1] is .numberCase")



func checkCase(lhsCase: MyEnum, rhsCase: MyEnum) -> Bool 
    if case lhsCase = rhsCase 
        return true
     else 
        return false
    


// Usage:
if checkCase(lhsCase: .justACase, rhsCase: myArray[0])  //<-- allows to pass variables or just the cases (unfortunately not without associated value.)
    print("myArray[0] is .justACase")


if case myArray[3] = myArray[0]  //<-- allows this here too
    print("myArray[0] is .justACase")


// Bonus: Adding equatable if associated values are not equatable. Looking at the case only.
extension MyEnum: Equatable 
    static func == (lhs: MyEnum, rhs: MyEnum) -> Bool 
        lhs.matches(case: rhs)
    


if myArray[3] == myArray[0] 
    print("myArray[3] == myArray[0]")

【讨论】:

以上是关于如何将枚举案例传递给使用“if case”检查属性案例的函数的主要内容,如果未能解决你的问题,请参考以下文章

如何将枚举作为字符串参数传递给 Authorize 属性?

ja对象属性—枚举检查删除

将枚举传递给方法[重复]

MySQL基础--08---流程控制( IF CASE) 和 游标

如何将枚举传递给 Html.RadioButtonFor 以获取 MVC 2 RC 2、C# 中的单选按钮列表

将枚举类型传递给具有整数值的转换器[重复]