有条件地符合Hashable

时间:2018-07-20 21:18:54

标签: swift conditional protocols

对于Xcode 10和Swift 4.2,还有其他符合Hashable的类型,只要它们的元素也符合HashableArrayDictionary等)即可

我目前在我的项目中有一些代码可以为Swift 4.1及以下版本添加Hashable一致性,

extension Array: Hashable where Element: Hashable {
  public var hashValue: Int {
    let prime = 31
    var result = 1
    for element in self {
      result = prime * result + element.hashValue
    }
    return result
  }
}

但是,即使我在代码周围添加#if !swift(>=4.2),我仍然在Xcode中看到相同的警告。

Xcode 10 Hashable Warning

我的问题是,如何在Swift 4.1及更低版本的条件下保持对Hashable的条件符合性,而对Swift 4.2保持警告状态呢?

1 个答案:

答案 0 :(得分:3)

条件编译语句#if swift(...)会与您运行的语言版本相对应-can differ from the compiler (and therefore standard library) version

在您的情况下,听起来好像您正在以Swift 4兼容模式使用Swift 4.2编译器,这为您提供了language version of 4.1.50。因此,这将传递条件编译语句,并且将对您的扩展进行编译,从而为您提供重复的一致性。

要检查低于4.2的编译器版本,您需要执行以下操作:

// less than 4.2 in Swift 4 compat mode and (less than 4.2 in 3 compat mode or
// greater than 4).
#if !swift(>=4.1.50) && (!swift(>=3.4) || swift(>=4.0))
extension Array : Hashable where Element : Hashable {
  public var hashValue: Int {
    let prime = 31
    var result = 1
    for element in self {
      result = prime * result + element.hashValue
    }
    return result
  }
}
#endif

使用the new #if compiler directive可以使事情变得更好,它可以从Xcode 10 beta 4起(confirmed by @MartinR)在Swift 4.2中获得。这样,您就可以直接测试编译器版本,而无需考虑其可能在其中运行的任何兼容模式。

这对您的特定情况没有帮助,因为您需要Swift 4.2和4.1编译器都可以理解代码(正如Martin所指出的),但是对于将来的兼容性问题,您可以使用{{1} },以便仅在使用4.2编译器的情况下编译代码块。