我怎么能做到这一点?

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


这意味着NSObjectString在某种程度上是AnyHashable的子类型,而AnyHashablestruct,那么,它们如何允许呢?

最佳答案

考虑到Optionalenum,它也是一个值类型-但是您可以自由地将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)




尽管很好奇Dictionaryalso implements an extension)的标准库@OOPer shows,允许将Key类型为AnyHashable的字典下标为任何_Hashable兼容类型(我不相信有符合_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中删除,描述如下:


  我们有一个隐式转换为AnyHashable,所以没有
  根本不需要在字典上有特殊的下标。


这证实了我的怀疑。

关于swift - 如何将Int和String接受为AnyHashable?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47269969/

10-14 21:58