Swift:枚举中元素的索引(CaseIterable)

cya*_*ide 6 enums swift

以下代码(编译时没有错误)检索特定 CaseIterable 枚举类型中元素的索引

public enum MyEnum : CaseIterable {
    case ONE, TWO, THREE

    public func ordinal() -> Int? {
       return MyEnum.allCases.firstIndex(of: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个通用函数来处理所有 CaseIterable 枚举。

如果我尝试:

 public extension CaseIterable {

    public func ordinal() -> Int? {
        return CaseIterable.allCases.firstIndex(of: self)
    }
 }
Run Code Online (Sandbox Code Playgroud)

我收到一个编译器错误“ Member 'allCases' cannot be used on value of protocol type 'CaseIterable'; use a generic constraint instead”,这是非常合乎逻辑的,因为实际的枚举类型未知”。

当我尝试时CaseIterable<T>,我收到另一个错误,因为 CaseIterable 未声明为泛型类型。

有办法吗?

Con*_*nor 14

需要进行一些更改:

  1. 返回类型需要是Self.AllCases.Index?而不是Int?。在实践中,这些类型将是等效的,如下所示。
  2. 您还需要将任何类型限制为Equatable,因为您需要相等才能使用firstIndex(of:). 同样,在实践中, anyCaseIterable通常是一个没有关联值的枚举,这意味着它会自动相等。
  3. (可选更改)此函数永远不会返回nil,因为您在CaseIterable. 因此,您可以删除返回类型 ( Self.AllCases.Index)的可选性并强制展开。

例子:

public extension CaseIterable where Self: Equatable {

    public func ordinal() -> Self.AllCases.Index {
        return Self.allCases.firstIndex(of: self)!
    }

}

enum Example: CaseIterable {

    case x
    case y

}

Example.y.ordinal()  // 1
type(of: Example.y.ordinal()) // Int
Run Code Online (Sandbox Code Playgroud)

就个人而言,我会补充说“Ordinal”通常意味着与您正在做的事情不同的东西,我建议将函数名称更改为elementIndex()或其他内容。但这是旁观。