Swift nil 任何 != nil [英] Swift nil Any != nil

查看:65
本文介绍了Swift nil 任何 != nil的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

斯威夫特 5.1.请考虑以下事项.

Swift 5.1 . Consider the following.

let x: Any? = nil
let y: Any = x
print("x \(x)")                      // x nil
print("type(of: x) \(type(of: x))")  // type(of: x) Optional<Any>
print("x == nil \(x == nil)")        // x == nil true
print("y \(y)")                      // y nil
print("type(of: y) \(type(of: y))")  // type(of: y) Optional<Any>
print("y == nil \(y == nil)")        // y == nil false

我们有两个变量,设置为相同的东西——nil.它们打印相同,它们的类型打印相同 - 但是一个 == nil 而另一个没有.

We have two variables, set equal to the same thing - nil. They print the same, their type prints the same - but one == nil and the other does not.

  1. 为什么?
  2. 给定这样一个Any,人们怎么会发现它实际上为零?
  1. Why?
  2. Given such an Any, how might one discover that it is, in fact, nil?

推荐答案

想想 AnyOptional 之类的盒子.

Think of Any and Optional<Wrapped> like boxes.

  1. Any 是一个不透明的盒子,可以装任何东西.您可以尝试使用 as? 对其进行投射,从而窥探其内部结构.
  2. Optional 是一个透明的盒子.它让您看到它的内容是 Optional.some(wrapped)Optional.none() 的值.
  1. Any is an opaque box that can hold anything. You can gleam what's inside by trying to cast it using as?.
  2. Optional<Wrapped> is a transparent box. It lets you see that its contents are either a value of Optional<Wrapped>.some(wrapped) or Optional<Wrapped>.none().

包含 OptionalOptionalAny 不是一回事.

An Optional<Any> and Any containing an Optional<Wrapped> aren't the same thing.

Optional.none 的值,也就是 nil.nil 被打印出来,所以这是有道理的.

is a value of Optional<Any>.none, a.k.a. nil. nil gets printed, so that makes sense.

x 的类型,Optional,正如我们预期的那样.

is the type of x, Optional<Any>, as we expected.

正在调用 (T, T) -> 类型的 == 运算符布尔.由于两个参数都需要是相同的类型,而且 x 的值是 Optional.none(类型为 Optional>),nil 被推断为 Optional.none.两者是等价的,所以我们得到 true,正如预期的那样.

is calling an == operator of type (T, T) -> Bool. Since both args need to be the same type, and since x has a value of Optional<Any>.none (of type Optional<Any>), nil is inferred to be Optional<Any>.none. The two are equivalent, so we get true, as expected.

Any 类型的值.在编译时,对 y 一无所知.恰巧隐藏在Any 不透明幕布背后的价值是x.print 被实现为透视"Any instances,向你展示真正存在的东西.

is a value of type Any. At compile time, nothing more is known about y. It just so happens that the value behind hidden by the opaque curtain of Any is x. print is implemented to "see through" Any instances, to show you what's really there.

正在做类似于 print 的事情.它使用运行时类型信息来准确查看存储在 y 中的运行时值是什么.y 的静态类型是 Any,但是 type(of: y) 告诉我们它的值的运行时类型是 Optional<任何>.

is doing something similar to print. It's using runtime type information to see exactly what the runtime value stored into y is. The static type of y is Any, but type(of: y) shows us that the runtime type of its value is Optional<Any>.

这是有点棘手的地方.

在编译时根据操作数的静态已知类型选择要调用的函数或运算符的重载.也就是说,操作符和函数不是根据参数的类型动态调度的,而是根据对象的类型动态调度的(例如 中的 foofoo.bar()).

The choice of which overload of a function or operator to call is done at compile time, based on the statically known types of the operands. That is to say, operators and functions aren't dynamically dispatched based on the types of their arguments, the way they're dynamically dispatched based on the type of their objects (e.g. the foo in foo.bar()).

这里选择的重载是 ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) ->布尔.您可以在 lines 4Optional.swift 的 481.

The overload that's selected here is ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool. You can see its implementation on lines 449-481 of Optional.swift.

它的左侧操作数是 Wrapped?,也就是 Optional.

Its left-hand-side operand is Wrapped?, a.k.a. an Optional<Wrapped>.

它的右侧操作数是 _OptionalNilComparisonType.这是一个符合ExpressibleByNilLiteral的特殊类型.

Its right-hand-side operand is _OptionalNilComparisonType. This is a special type that conforms to ExpressibleByNilLiteral.

Optional 是一种符合 ExpressibleByNilLiteral 的类型,这意味着你可以写 let x: Optional= nil,并且编译器可以使用该协议来理解 nil 应该表示 Optional.none.ExpressibleByNilLiteral 协议的存在允许此行为可以被其他类型扩展.例如,您可以想象一个 Python 互操作性框架,您希望能够在其中说 let none: PyObject = nil,它可以传递到 Python 并解析为None,Python 的 null 类型.

Optional is one type that conforms to ExpressibleByNilLiteral, meaning that you can write let x: Optional<Int> = nil, and the compiler could use that protocol to understand that nil should mean Optional<Int>.none. The ExpressibleByNilLiteral protocol exists to allow this behaviour to be extensible by other types. For example, you can imagine a Python interopability framework, where you would want to be able to say let none: PyObject = nil, which could be passed into Python and resolve to None, Python's null type.

这里发生的事情是左侧(yAny 类型)被提升为Any? 类型.提升值的类型为 Optional.some(old_value_of_y).右侧的 nil 用于实例化 _OptionalNilComparisonType 的值,相当于调用 _OptionalNilComparisonType.init(nilLiteral: ()).

What's happening here is that the left hand side (y, of type Any), is being promoted to type Any?. The promoted value has type Optional<Any>.some(old_value_of_y). The right hand side, the nil, is being used to instantiate a value of _OptionalNilComparisonType, equivalent to calling _OptionalNilComparisonType.init(nilLiteral: ()).

因此,您的呼叫站点相当于:

Thus, your call site is equivalent to:

Optional<Any>.some((Optional<Any>.none) as Any) == _OptionalNilComparisonType(nilLiteral: ()) /*
↑                  ↑↖︎_the value of x_↗︎       ↑↑
↑                  ↖︎_the value of y _________↗︎↑
↖︎_the value of y after promotion to optional__↗︎ */

根据实现,左边是一个some,右边是一个nil,因此它们是不相等的.

According to the implementation, the left side is a some, the right side is a nil, and thus they're unequal.

你可能会说:

这是非常不明显的行为,这不是我想要的.

Well this is pretty non-obvious behaviour, it's not what I wanted.

我会回应:

不要忽略编译器错误,它们是正确的:

Don't ignore the compiler errors, they're right on point:

警告:将 Any 类型的非可选值与 nil 进行比较总是返回 false

warning: comparing non-optional value of type Any to nil always returns false

这篇关于Swift nil 任何 != nil的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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