当前位置 : 主页 > 手机开发 > 其它 >

swift – 如何将Int和String作为AnyHashable接受?

来源:互联网 收集:自由互联 发布时间:2021-06-11
我怎么能这样做? var dict = [AnyHashable : Int]() dict[NSObject()] = 1 dict[""] = 2 这意味着NSObject和String在某种程度上是AnyHashable的子类型,但AnyHashable是一个结构,所以他们如何允许这个? 考虑到
我怎么能这样做?

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, 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: %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.

这证实了我的怀疑.

网友评论