var dict = [AnyHashable : Int]() dict[NSObject()] = 1 dict[""] = 2
这意味着NSObject和String在某种程度上是AnyHashable的子类型,但AnyHashable是一个结构,所以他们如何允许这个?
解决方法
Optional
是一个枚举,它也是一个值类型 – 但您可以自由地将String转换为Optional< String>.答案很简单,编译器会隐式地为您执行这些转换.
如果我们查看以下代码发出的SIL:
let i: AnyHashable = 5
我们可以看到编译器插入了对_swift_convertToAnyHashable的调用:
// allocate memory to store i,and get the address. alloc_global @main.i : Swift.AnyHashable,loc "main.swift":9:5,scope 1 // id: %2 %3 = global_addr @main.i : Swift.AnyHashable : $*AnyHashable,scope 1 // user: %9 // allocate temporary storage for the Int,and intialise it to 5. %4 = alloc_stack $Int,loc "main.swift":9:22,scope 1 // users: %7,%10,%9 %5 = integer_literal $Builtin.Int64,5,scope 1 // user: %6 %6 = struct $Int (%5 : $Builtin.Int64),scope 1 // user: %7 store %6 to %4 : $*Int,scope 1 // id: %7 // call _swift_convertToAnyHashable,passing in the address of i to store the result,and the address of the temporary storage for the Int. // function_ref _swift_convertToAnyHashable %8 = function_ref @_swift_convertToAnyHashable : $@convention(thin) <τ_0_0 where τ_0_0 : Hashable> (@in τ_0_0) -> @out AnyHashable,scope 1 // user: %9 %9 = apply %8<Int>(%3,%4) : $@convention(thin) <τ_0_0 where τ_0_0 : Hashable> (@in τ_0_0) -> @out AnyHashable,scope 1 // deallocate temporary storage. dealloc_stack %4 : $*Int,scope 1 // id: %10
查看AnyHashable.swift,我们可以看到函数的silgen名称为_swift_convertToAnyHashable
,它只调用AnyHashable
‘s initialiser.
@_silgen_name("_swift_convertToAnyHashable") public // COMPILER_INTRINSIC func _convertToAnyHashable<H : Hashable>(_ value: H) -> AnyHashable { return AnyHashable(value) }
因此,上面的代码只相当于:
let i = AnyHashable(5)
虽然很奇怪标准库also implements an extension for Dictionary(@OOPer shows),允许具有AnyHashable类型的Key的字典由任何_Hashable一致类型下标(我不相信有任何类型符合_Hashable,但不是哈希的).
对于_Hashable键,下标本身应该可以正常工作而没有特殊的重载.相反,默认的下标(将采用AnyHashable键)可以与上面的隐式转换一起使用,如下例所示:
struct Foo { subscript(hashable: AnyHashable) -> Any { return hashable.base } } let f = Foo() print(f["yo"]) // yo
编辑:在Swift 4中,上述下标重载和_Hashable都已于this commit从stdlib中删除,描述如下:
We have an implicit conversion to AnyHashable,so there’s no
need to have the special subscript on Dictionary at all.
这证实了我的怀疑.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。