加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-14 04:38:14 所属栏目:百科 来源:网络整理
导读:我怎么能这样做? var dict = [AnyHashable : Int]() dict[NSObject()] = 1 dict[""] = 2 这意味着NSObject和String在某种程度上是AnyHashable的子类型,但AnyHashable是一个结构,所以他们如何允许这个? 解决方法 考虑到 Optional 是一个枚举,它也是一个值类
我怎么能这样做?

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.

这证实了我的怀疑.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读