用于检查案例的Swift通用枚举函数

用于检查案例的Swift通用枚举函数,swift,Swift,如果枚举实例是枚举类型,是否可以创建一个返回布尔值的泛型枚举函数,或者这是否已经存在并且我不知道 我在项目中使用了大量枚举。我经常用关联的值定义枚举 简单的例子: enum Mode { case new case edit(Record) // Record is a struct type } 我定期检查枚举实例是否是特定的枚举实例。但是,很多时候,我不需要检查关联的值。我在找一个方便的方法来检查这个案子。我知道的每种方法都有缺点 方法1-2:如果案例模式匹配或切换

如果枚举实例是枚举类型,是否可以创建一个返回布尔值的泛型枚举函数,或者这是否已经存在并且我不知道


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

简单的例子:

enum Mode {
    case new
    case edit(Record)    // Record is a struct type
}
我定期检查枚举实例是否是特定的枚举实例。但是,很多时候,我不需要检查关联的值。我在找一个方便的方法来检查这个案子。我知道的每种方法都有缺点

方法1-2:如果案例模式匹配或切换案例 缺点:

  • 无法将检查直接分配给变量。我们必须在结束时这样做
  • 无法将此模式直接用作函数的参数
方法3-5实现枚举函数或计算属性或可等式协议的检查值 缺点:

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

相反,我正在寻找一种方法来编写一个泛型函数,该函数在枚举实例与枚举实例匹配时返回布尔值。可以写入一次并应用于所有枚举的内容。类似于结构和类类型的通用函数:

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

    return a is S   // though you could just call this directly
}
func-checkType(a:T,\u:S.Type)->Bool{
返回a为S//尽管您可以直接调用它
}

我认为没有一个好的惯用方法来实现这一点。想到的唯一一件事是将枚举实例的原始内存与具有所需大小写的伪实例进行比较

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

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
        }
    }
}

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

首先。谢谢你的回答。如果没有别的,它证实了我的怀疑,即没有一个完美的方法来做到这一点。一、 然而,不要认为我会在生产代码中使用它,当一天结束时,我只是避免实现已知的、安全的解决方案,即使它们是重复的。我会让这件事再持续几天,希望能有更多的答案。如果这是我们所能做的最好的,那么我将标记正确,作为学术解决方案。
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