Swift 当Set.insert()返回可与newMember区分的oldMember时?

Swift 当Set.insert()返回可与newMember区分的oldMember时?,swift,set,Swift,Set,Set的insert方法的文档: 返回值 (true,newMember)如果newMember未包含在集合中。如果集合中已包含等于newMember的元素,则该方法返回(false,oldMember),其中oldMember是等于newMember的元素 在某些情况下,oldMember可以通过身份比较或其他方式与newMember区分开来 当oldMember与他们正在谈论的newMember有区别时,会出现什么情况?有什么例子吗 问题原因:我有一个集合,其中包含的对象不一定是可散列的。我

Set
insert
方法的文档:

返回值

(true,newMember)
如果
newMember
未包含在集合中。如果集合中已包含等于
newMember
的元素,则该方法返回
(false,oldMember)
,其中
oldMember
是等于
newMember
的元素

在某些情况下,
oldMember
可以通过身份比较或其他方式与
newMember
区分开来

oldMember
与他们正在谈论的
newMember
有区别时,会出现什么情况?有什么例子吗


问题原因:我有一个
集合
,其中包含的对象不一定是
可散列的
。我的想法是使用
Unmanaged.passUnretained(object).toOpaque().hashValue
为包装结构中的任何对象(基本上是从其地址)获取哈希值,然而,文档中的上述内容让我感到警惕。

如果您有办法区分两个实例,即使它们通过实现
equalable
=
运算符进行比较,也可以使用它将要插入的元素与
插入(\u:.)返回的
memberAfterInsert
进行比较

如文档所述,这方面的一个主要示例是身份比较(
==
)。比较相等的两个对象实例不一定是完全相同的实例(即具有相同的地址)

例如:

class Foo : Hashable {

    static func ==(lhs: Foo, rhs: Foo) -> Bool {
        return lhs.foo == rhs.foo
    }

    var hashValue: Int {
        return foo
    }

    let foo: Int

    init(_ foo: Int) {
        self.foo = foo
    }
}

var set : Set = [Foo(10)]

let toInsert = Foo(10)
let result = set.insert(toInsert) // the element toInsert will compare equal to the element
                                  // already in the set, thus the element already in the
                                  // already in the set will be returned.

print(result) // (false, Foo) – false, as element was already in set
print(result.memberAfterInsert == toInsert) // true – obviously they were equal.
print(result.memberAfterInsert === toInsert) // false – but they weren't the same instance.
在使用基于标识的哈希值的情况下,只要
equalable
实现也依赖于标识,就不会违反
Hashable
的约定(与
==
比较相等的实例必须具有相同的
hashValue
)–虽然很明显,您将无法使用标识来区分
memberAfterInsert
与您尝试插入的元素


但是,值得注意的是,如果
元素的相等实现完全基于标识,那么使用
集合
,可能会对看起来应该相等的对象产生令人惊讶的结果。例如,如果对象是不同的实例,那么拥有一组
[Foo(5),Foo(5),Foo(5),Foo(5)]
就很好了。

注意,基于对象地址获取
hashValue
的更简单方法是
ObjectIdentifier(object)。hashValue
@Hamish,顺便说一句,感谢您提供有关
ObjectIdentifier
的提示。感谢您提供此示例。为了澄清这段话,“在您使用基于标识的哈希值的情况下……显然,您将无法使用标识来区分memberAfterInsert和您插入的元素”。在这种情况下,我希望只有当插入的对象确实已经存在时,插入才会返回
false
,对吗?所以身份检查仍然有效。@AntonBronnikov要插入的元素和
memberAfterInsert
之间的身份检查将始终返回true–就好像
==
基于身份,那么如果集合中已经存在相同的元素,将返回该元素,并将其与要插入的元素进行比较。如果元素不在集合中,则要插入的元素将直接从函数中传递回来,再次比较true。