Swift 5.0“设置”允许重复值

时间:2019-07-09 05:38:42

标签: swift hash set equality

在Swift 5.0 Playground中,我正在对CGPoint进行扩展,以使其在哈希和相等性方面将点视为整数值。

令我惊讶的是,即使在hash()上覆盖了==CGPoint之后,一组CGPoint仍然具有与独立点相似的值,即使两个元素应该发生碰撞并且只保留了一个。您是否需要在CGPoint上覆盖其他方法才能按预期进行这项工作?

P.S。在实践中最好不要这样做,因为它可能会影响系统,最好提供某种包装程序来管理平等性。但是我想知道为什么这行不通。

Playground的内容以及执行后给出的结果:

// Extension to treat points as integer values (not reccomended approach)
extension CGPoint : Hashable {
    public func hash(into hasher: inout Hasher) {
                hasher.combine(Int(x))
        hasher.combine(Int(y))
    }

    static public func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
        return Int(lhs.x) == Int(rhs.x) && Int(lhs.y) == Int(rhs.y)
    }
}

var pSet : Set<CGPoint> = []

let p1 = CGPoint.zero
let p2 =  CGPoint(x: 20.1, y: 30)
let p3 =  CGPoint(x:20, y: 30)

pSet.insert(p1) // inserted true
pSet.insert(p2) // inserted true
pSet.insert(p3) // inserted true(!), should be false

p2 == p3 // true

pSet.count // 3(!), should be two
p2.hashValue  // Same as p3
p3.hashValue  // Same as p2

pSet // shows all three values, all points defined, should be two values only

1 个答案:

答案 0 :(得分:2)

rmaddy和Martin R发现了问题,但这是一个答案:Set不使用您的==函数。它使用标准库中定义的==函数,因为Set是在标准库中定义的。您可以通过调用print==函数来证明这一点。将点插入Set时,您会看到print没有运行。