我怎么能这样做?
var dict = [AnyHashable : Int]()
dict[NSObject()] = 1
dict[""] = 2
Run Code Online (Sandbox Code Playgroud)
这意味着,NSObject和String在某种程度上一个亚型的AnyHashable却AnyHashable是struct这样,他们怎么允许这样做?
考虑这Optional是一个enum,也是一个值类型 - 然而你可以自由地将a转换String为Optional<String>.答案很简单,编译器会隐式地为您执行这些转换.
如果我们查看以下代码发出的SIL:
let i: AnyHashable = 5
Run Code Online (Sandbox Code Playgroud)
我们可以看到编译器插入一个调用_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, loc "main.swift":9:5, 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, loc "main.swift":9:22, scope 1 // user: %6
%6 = struct $Int (%5 : $Builtin.Int64), loc "main.swift":9:22, scope 1 // user: %7
store %6 to %4 : $*Int, loc "main.swift":9:22, 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, loc "main.swift":9:22, scope 1 // user: %9
%9 = apply %8<Int>(%3, %4) : $@convention(thin) <?_0_0 where ?_0_0 : Hashable> (@in ?_0_0) -> @out AnyHashable, loc "main.swift":9:22, scope 1
// deallocate temporary storage.
dealloc_stack %4 : $*Int, loc "main.swift":9:22, scope 1 // id: %10Run Code Online (Sandbox Code Playgroud)
查看AnyHashable.swift,我们可以看到具有silgen名称的函数_swift_convertToAnyHashable,它只是调用AnyHashable初始化函数.
@_silgen_name("_swift_convertToAnyHashable")
public // COMPILER_INTRINSIC
func _convertToAnyHashable<H : Hashable>(_ value: H) -> AnyHashable {
return AnyHashable(value)
}
Run Code Online (Sandbox Code Playgroud)
因此,上面的代码只相当于:
let i = AnyHashable(5)
Run Code Online (Sandbox Code Playgroud)
虽然这是奇怪的是,标准库还实现了一个扩展的Dictionary(这@OOPer节目),允许带字典Key类型的AnyHashable受任何被下标_Hashable贴合型(我不相信有符合任何类型_Hashable,但不Hashable).
下标本身应该可以正常工作而没有特殊的_Hashable密钥重载.相反,默认的下标(AnyHashable可以使用键)可以与上面的隐式转换一起使用,如下例所示:
struct Foo {
subscript(hashable: AnyHashable) -> Any {
return hashable.base
}
}
let f = Foo()
print(f["yo"]) // yo
Run Code Online (Sandbox Code Playgroud)
编辑:在Swift 4中,前面提到的下标重载_Hashable都已经通过此提交从stdlib中删除了描述:
我们有一个隐式转换为AnyHashable,因此根本不需要在Dictionary上有特殊的下标.
这证实了我的怀疑.
| 归档时间: |
|
| 查看次数: |
2632 次 |
| 最近记录: |