问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/53805768/why-do-we-need-to-explicitly-cast-the-optional-to-any