Int 和 String 如何被接受为 AnyHashable? [英] How are Int and String accepted as AnyHashable?

查看:11
本文介绍了Int 和 String 如何被接受为 AnyHashable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎么能做到这一点?

    var dict = [AnyHashable : Int]()
    dict[NSObject()] = 1
    dict[""] = 2

这意味着 NSObjectString 在某种程度上是 AnyHashablesubtypeAnyHashable 是一个 struct 那么,他们如何允许这个?

This implies that NSObject and String are somehow a subtype of AnyHashable but AnyHashable is a struct so, how do they allow this?

推荐答案

考虑到 Optional 是一个 enum,它也是一种值类型——但你可以自由地将 String 转换为 Optional<字符串>.答案很简单,编译器会为您隐式地执行这些转换.

Consider that Optional is an enum, which is also a value type – and yet you're freely able to convert a String to an Optional<String>. The answer is simply that the compiler implicitly performs these conversions for you.

如果我们查看为以下代码发出的 SIL:

If we look at the SIL emitted for the following code:

let i: AnyHashable = 5

我们可以看到编译器插入了对_swift_convertToAnyHashable的调用:

We can see that the compiler inserts a call to _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,我们可以看到带有 _swift_convertToAnyHashable,它只是调用 AnyHashable 的初始化程序.

Looking in AnyHashable.swift, we can see the function with the silgen name of _swift_convertToAnyHashable, which simply invokes AnyHashable's initialiser.

@_silgen_name("_swift_convertToAnyHashable")
public // COMPILER_INTRINSIC
func _convertToAnyHashable<H : Hashable>(_ value: H) -> AnyHashable {
  return AnyHashable(value)
}

因此上面的代码就等价于:

Therefore the above code is just equivalent to:

let i = AnyHashable(5)

<小时>

虽然奇怪的是标准库 还为Dictionary实现了一个扩展(@OOPer 显示),允许对于具有 AnyHashable 类型的 Key 的字典,下标为任何 _Hashable 符合类型(我不相信有任何类型符合到 _Hashable,但不是 Hashable).


Although it's curious that the standard library also implements an extension for Dictionary (which @OOPer shows), allowing for a dictionary with a Key of type AnyHashable to be subscripted by any _Hashable conforming type (I don't believe there are any types that conform to _Hashable, but not Hashable).

下标本身应该可以正常工作,无需对 _Hashable 键进行特殊重载.相反,默认下标(将采用 AnyHashable 键)可以仅用于上述隐式转换,如以下示例所示:

The subscript itself should work fine without a special overload for _Hashable keys. Instead the default subscript (which would take an AnyHashable key) could just be used with the above implicit conversion, as the following example shows:

struct Foo {
    subscript(hashable: AnyHashable) -> Any {
        return hashable.base
    }
}

let f = Foo()
print(f["yo"]) // yo

编辑:在 Swift 4 中,上述下标重载和 _Hashable 已被 这个提交 和描述:

Edit: In Swift 4, both the aforementioned subscript overload and _Hashable have been removed from the stdlib by this commit with the description:

我们有一个到 AnyHashable 的隐式转换,所以没有完全需要在 Dictionary 上有特殊的下标.

We have an implicit conversion to AnyHashable, so there's no need to have the special subscript on Dictionary at all.

这证实了我的怀疑.

这篇关于Int 和 String 如何被接受为 AnyHashable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆