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

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

    public func ordinal() -> Int? {
       return MyEnum.allCases.firstIndex(of: self)
    }
}

我想做一个通用的函数来与所有CaseIterable枚举一起使用。

如果我尝试:
 public extension CaseIterable {

    public func ordinal() -> Int? {
        return CaseIterable.allCases.firstIndex(of: self)
    }
 }

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

当我尝试CaseIterable<T>时,出现另一个错误,因为CaseIterable没有声明为泛型类型。

有办法吗?

最佳答案

需要进行一些更改:

  • 返回类型必须是Self.AllCases.Index?而不是Int?。实际上,这些类型将是等效的,如下所示。
  • 您还需要将任何类型限制为Equatable,因为您必须是等价的才能使用firstIndex(of:)。同样,在实践中,任何CaseIterable通常都是没有关联值的枚举,这意味着它会自动变为等值。
  • (可选更改)此函数将永远不会返回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
    

    就个人而言,我要补充一点,“序数”通常意味着与您正在执行的操作有所不同,并且我建议将函数名称更改为elementIndex()或其他名称。但这是一个问题。

    关于swift - Swift:枚举中元素的索引(CaseIterable),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54932863/

    10-11 14:36