【问题标题】:Swift Generic enum function to check case用于检查大小写的 Swift 通用枚举函数
【发布时间】:2017-03-25 23:06:27
【问题描述】:

如果枚举实例是枚举类型或者它已经存在但我不知道,是否可以创建一个返回布尔值的通用枚举函数?


我在我的项目中使用了大量的枚举。我经常用关联的值定义枚举。

简单示例:

enum Mode {
    case new
    case edit(Record)    // Record is a struct type
}

我会定期检查一个枚举实例是否是一个特定的枚举案例。但是,很多时候,我不需要检查关联的值。我正在寻找一种方便的方法来检查案件。我知道的每种方法都有缺点。

方法1-2:If Case模式匹配或Switch case

let myMode = Mode.edit
if case Mode.edit(_) = myMode {
    // do something
}

switch mode {
case .edit:
    // do something
default:
    break    
}

缺点:

  • 无法直接将检查分配给变量。必须在关闭时这样做
  • 不能将此模式直接用作函数的参数

方法3-5 实现枚举函数或检查计算属性或Equatable协议的值

缺点:

  • 必须为每个枚举类型实现

相反,我正在寻找一种方法来编写一个通用函数,如果枚举实例匹配一个枚举大小写,则该函数返回一个布尔值。可以编写一次并应用于所有枚举的东西。类似于 Struct 和 Class 类型的通用函数:

func checkType<T, S> (a: T, _: S.Type) -> Bool {

    return a is S   // though you could just call this directly
}

【问题讨论】:

    标签: swift


    【解决方案1】:

    我认为没有一种很好的惯用方式来实现这一点。唯一想到的是将枚举实例的原始内存与具有所需案例的虚拟实例进行比较。

    由于我们不关心关联值,我们只需要要求它们各自的最后一个字节相同。

    func unsafeEqualityLastByteOnly<A>(_ lhs: A, _ rhs: A) -> Bool {
        var (lhs, rhs) = (lhs, rhs)
    
        let offset = MemoryLayout<A>.size - 1
    
        return withUnsafePointer(to: &lhs) { lhsPtr in
            withUnsafePointer(to: &rhs) { rhsPtr in
                let lhsPtr = unsafeBitCast(lhsPtr, to: UnsafeRawPointer.self)
                let rhsPtr = unsafeBitCast(rhsPtr, to: UnsafeRawPointer.self)
    
                return memcmp(lhsPtr.advanced(by: offset), rhsPtr.advanced(by: offset), 1) == 0
            }
        }
    }
    

    这远非漂亮,但它确实有效。

    enum Test {
        case a(Int)
        case b(Int)
    }
    
    let a1 = Test.a(1)
    let a2 = Test.a(2)
    
    let b1 = Test.b(1)
    let b2 = Test.b(2)
    
    unsafeEqualityLastByteOnly(a1, a1) // true
    unsafeEqualityLastByteOnly(a1, a2) // true
    unsafeEqualityLastByteOnly(a2, a2) // true
    
    unsafeEqualityLastByteOnly(b1, b1) // true
    unsafeEqualityLastByteOnly(b1, b2) // true
    unsafeEqualityLastByteOnly(b2, b2) // true
    
    unsafeEqualityLastByteOnly(a1, b1) // false
    unsafeEqualityLastByteOnly(a1, b2) // false
    unsafeEqualityLastByteOnly(a2, b1) // false
    unsafeEqualityLastByteOnly(a2, b2) // false
    

    使用您自己的判断来决定这是否是您在项目中想要的东西。这显然不是一个应该毫无保留地推荐的技术。

    【讨论】:

    • 第一。感谢您的回答。如果不出意外,它证实了我的怀疑,即没有完美的方法来做到这一点。但是,我认为我不会在生产代码中使用它,最终,我只是避免实施已知的安全解决方案,即使它们是重复的。我会让这个再坐几天,希望有更多的答案。如果这是我们能做的最好的,那么我会标记为正确的,用于学术解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 2022-07-08
    相关资源
    最近更新 更多