为什么我们需要将可选选项显式转换为Any? [英] Why do we need to explicitly cast the optional to Any?

查看:96
本文介绍了为什么我们需要将可选选项显式转换为Any?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Apple Doc

Any类型表示任何类型的值,包括可选类型. 如果您使用可选值(其中一个值 预期类型为Any.如果确实需要使用可选的 值作为Any值,您可以使用as运算符来显式转换 可选的Any,如下所示.

var things = [Any]()
things.append(3)                     // No warning
let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning, even though Any also represents optional types.
things.append(optionalNumber as Any) // No warning

为什么我们需要将可选内容显式转换为Any?

解决方案

每种类型都可以隐式提升为该类型的可选类型.这意味着,当将T?强制转换为Any时,很难知道它是最初的T还是最初的T?(甚至是T??或更差).最令人困惑的是,可以将Any提升为Any?并且Any?Any类型,因此要说出AnyAny?Any??Any???之间的区别(等等. )非常棘手,有时甚至是不可能的.

Any在Swift中是一个非常棘手的类型,几乎不应该使用.除了显式欺骗编译器(在一些非常花哨和脆弱的类型擦除器中)之外,我不知道将Any作为变量类型确实有意义,并且绝对不采用.如果您创建的是[Any],则说明您走了一条不好的路,

在极少数情况下,将Any作为函数参数类型是有意义的(print()是最著名的),但是在应用程序级代码中极为罕见.如果您发现自己需要Any,则可能是做错了什么,编译器会为此大惊小怪,并经常使您编写额外的as代码以确保您的意思确实是杂乱无章的说.

仅给出具体的解释,当您输入Any时,可选性往往会丢失.因此,请考虑这种情况:

let number: Int = 3
let optionalNumber: Int? = 3
let nilNumber: Int? = nil

let anyNumber = number as Any
let anyOptional = optionalNumber as Any
let anyNil = nilNumber as Any

if anyNumber is Int { print("number is Int")} // yes
if anyOptional is Int { print("optional number is Int")} // yes
if anyNil is Int { print("nil is Int")} // no

if anyNil is Int? { print("nil is Int?")}
// -> Error: Cannot downcast from 'Any' to a more optional type 'Int?'

老鼠.

我们无法以与放入可选方式相同的方式获得可选配件.我们当然可以对其进行推广:

if (anyNil as Any?) is Int? { print("nil is Int?") }  // yes

但是我们可以采用任何方式进行推广,因为所有内容本身都是可选的:

if (anyNumber as Any?) is Int? { print("number is Int?")}  // also yes

所以,嗯.老鼠我们真的不知道它最初是否是可选的.情况一团糟,编译器警告您,如果您走的很远,那将会是一团糟. T-> Any有点神奇. T-> T?也是一点魔力.结合这两种魔术,您最好确切地知道自己在做什么.

According to Apple Doc,

The Any type represents values of any type, including optional types. Swift gives you a warning if you use an optional value where a value of type Any is expected. If you really do need to use an optional value as an Any value, you can use the as operator to explicitly cast the optional to Any, as shown below.

var things = [Any]()
things.append(3)                     // No warning
let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning, even though Any also represents optional types.
things.append(optionalNumber as Any) // No warning

Why do we need to explicitly cast the optional to Any?

解决方案

Every type can be implicitly promoted to an optional of that type. This means that when you cast T? to Any it is very hard to know whether it was originally T or originally T? (or even T?? or worse). Most confusing is that Any can be promoted to Any? and that Any? is of type Any, so telling the difference between Any, Any?, Any??, and Any??? (etc.) is very tricky, and sometimes impossible.

Any is a very tricky type in Swift and should almost never be used. Except for explicitly tricking the compiler (in some very fancy and fragile type-eraser), I don't know of any case where it really makes sense to have Any as a variable type, and definitely not in the form of [Any]. If you're created an [Any], you've gone down a bad path that isn't going to go well.

There are a very few cases where Any as a function parameter type makes sense (print() being the most famous), but they are extremely rare in app-level code. If you find yourself needing Any, you've probably done something wrong, and the compiler is going to fuss at you about it and often make you write extra as code to make sure you really mean the messy things you're saying.

Just to give some concrete versions of this, optionality tends to be lost when you enter Any. So consider this situation:

let number: Int = 3
let optionalNumber: Int? = 3
let nilNumber: Int? = nil

let anyNumber = number as Any
let anyOptional = optionalNumber as Any
let anyNil = nilNumber as Any

if anyNumber is Int { print("number is Int")} // yes
if anyOptional is Int { print("optional number is Int")} // yes
if anyNil is Int { print("nil is Int")} // no

if anyNil is Int? { print("nil is Int?")}
// -> Error: Cannot downcast from 'Any' to a more optional type 'Int?'

Rats.

We can't get our optional back the same way we put it in. We can promote it of course:

if (anyNil as Any?) is Int? { print("nil is Int?") }  // yes

But we can promote anything that way, since everything is implicitly an optional of itself:

if (anyNumber as Any?) is Int? { print("number is Int?")}  // also yes

So, um. Rats. We don't really know if it was originally optional or not. It's mess, and the compiler is warning you that it's going to be a mess if you go very far down this road. T->Any is a bit of magic. T->T? is also a bit of magic. Combine the two magics, and you had better know exactly what you're doing.

这篇关于为什么我们需要将可选选项显式转换为Any?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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