二元运算符“*"不能应用于“Float"和“Float!"类型的操作数 [英] Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'
问题描述
当我执行以下操作时:
let gapDuration = Float(self.MONTHS) * Float(self.duration) * self.gapMonthly;
我收到错误:
Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'
但是当我这样做时:
let gapDuration = 12 * Float(self.duration) * self.gapMonthly;
一切正常.我不知道这个错误告诉我什么.
Everything is working fine. I have no Idea what this error is telling me.
self.gapMonthly
是 Float!
类型,self.duration
和 self.MONTHS
是类型Int!
self.gapMonthly
is of type Float!
and self.duration
and self.MONTHS
are of type Int!
推荐答案
我认为这是一个错误(至少,该错误具有误导性),并且在尝试在 3 或对给定类型求值的更多表达式,其中一个或多个表达式是该类型的隐式展开的可选项.
I would consider this a bug (at the very least, the error is misleading), and appears to be present when attempting to use a binary operator on 3 or more expressions that evaluate to a given type, where one or more of those expressions is an implicitly unwrapped optional of that type.
这只是将类型检查器延伸得太远,因为它必须考虑将 IUO 视为强可选的所有可能性(由于 SE-0054 编译器会将 IUO 视为强可选,如果它可以作为一个进行类型检查),以及尝试为运算符找到正确的重载.
This simply stretches the type-checker too far, as it has to consider all possibilities of treating the IUO as a strong optional (as due to SE-0054 the compiler will treat an IUO as a strong optional if it can be type-checked as one), along with attempting to find the correct overloads for the operators.
乍一看,它似乎类似于如何在 swift 3.0 中连接多个可选字符串? – 然而这个错误在 Swift 3.1 中被修复了,但是这个错误仍然存在.
At first glance, it appears to be similar to the issue shown in How can I concatenate multiple optional strings in swift 3.0? – however that bug was fixed in Swift 3.1, but this bug is still present.
重现相同问题的最小示例是:
A minimal example that reproduces the same issue would be:
let a: Float! = 0
// error: Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'
let b = a * a * a
并且存在于除 *
之外的其他二元运算符:
and is present for other binary operators other than *
:
// error: Binary operator '+' cannot be applied to operands of type 'Float' and 'Float!'
let b = a + a + a
混入 Float
表达式时(只要至少保留一个 Float!
表达式),以及显式注释 b 时,它仍然可以重现
作为 Float
:
It is also still reproducible when mixing in Float
expressions (as long as at least one Float!
expression remains), as well as when explicitly annotating b
as a Float
:
let b: Float = a * a * a // doesn't compile
let a: Float! = 0
let b: Int = 0
let c: Int = 0
let d: Float = a * Float(b) * Float(c) // doesn't compile
<小时>
对此的一个简单解决方法是显式强制解包表达式中隐式解包的可选项:
A simple fix for this would be to explicitly force unwrap the implicitly unwrapped optional(s) in the expression:
let d = a! * Float(b) * Float(c) // compiles
这减轻了类型检查器的压力,因为现在所有的表达式都计算为 Float
,所以重载解析要简单得多.
This relieves the pressure on the type-checker, as now all the expressions evaluate to Float
, so overload resolution is much simpler.
当然,不用说,如果 a
为 nil
,这会崩溃.一般来说,你应该尽量避免使用隐式解包的选项,而更喜欢使用强选项——并且,正如 @vadian 说,在 nil
值不存在的情况下,总是使用非可选项有道理.
Although of course, it goes without saying that this will crash if a
is nil
. In general, you should try and avoid using implicitly unwrapped optionals, and instead prefer to use strong optionals – and, as @vadian says, always use non-optionals in cases where the value being nil
doesn't make sense.
如果您需要使用可选项并且不能 100% 确定它包含一个值,您应该在进行算术运算之前安全地解开它.一种方法是使用 Optional
的 map(_:)
方法以传播可选性:
If you need to use an optional and aren't 100% sure that it contains a value, you should safely unwrap it before doing the arithmetic. One way of doing this would be to use Optional
's map(_:)
method in order to propagate the optionality:
let a: Float! = 0
let b: Int = 0
let c: Int = 0
// the (a as Float?) cast is necessary if 'a' is an IUO,
// but not necessary for a strong optional.
let d = (a as Float?).map { $0 * Float(b) * Float(c) }
如果a
非零,d
将被初始化为a
的解包值乘以Float 的结果(b)
和 Float(c)
.然而,如果 a
是 nil
,d
将被初始化为 nil
.
If a
is non-nil, d
will be initialized to the result of the unwrapped value of a
multiplied with Float(b)
and Float(c)
. If however a
is nil
, d
will be initialised to nil
.
这篇关于二元运算符“*"不能应用于“Float"和“Float!"类型的操作数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!