如何解决将非转义的值转换为“任意”可能会使其避免错误-在不转义的函数内
我的问题来自以下日语问题。 这不是我的问题,但我正在尝试回答以下问题,但找不到合适的答案。
https://teratail.com/questions/298998
上面的问题将像下面这样简单。
func executetwice(operation:() -> Void) {
print(operation)
operation()
}
此编译器需要在@escaping
标签后添加operation:
关键字,例如
func executetwice(operation: @escaping () -> Void) {
print(operation)
operation()
}
但是实际上,似乎operation
块不会从该块中逸出。
另一种方式,
func executetwice(operation:() -> Void) {
let f = operation as Any
operation()
}
编译器还需要添加@escaping
关键字。它只是向Any
转移。
在其他情况下,仅强制转换为相同类型,这似乎是错误的。
func executetwice(operation:() -> Void) {
let f = operation as () -> Void //Converting non-escaping value to '() -> Void' may allow it to escape
operation()
}
我不确定为什么要添加没有转义条件的@escaping
关键字。
只需添加@escaping
关键字就可以了,但是我想知道为什么在这种情况下编译器需要关键字。
解决方法
print
接受Any
作为变量,这就是为什么当您将闭包传递给{{1}时将其转换为Any
的原因}。
对闭包类型的参数进行了许多检查,以确保未转义的闭包不会逸出(对于闭包“转义”意味着什么,请阅读this):
print
但是,这些检查仅适用于闭包类型。如果将闭包强制转换为var c: (() -> Void)?
func f(operation:() -> Void) {
c = operation // compiler can detect that operation escapes here,and produces an error
}
,则闭包将丢失其闭包类型,并且编译器无法检查其是否转义。假设编译器允许您将非转义的闭包强制转换为Any
,并将其传递给下面的Any
:
g
因此,编译器的设计较为保守,将“广播到var c: Any?
func g(operation: Any) {
// the compiler doesn't know that "operation" is a closure!
// You have successfully made a non-escaping closure escape!
c = operation
}
”视为“使闭包转义”。
但是我们确定Any
不会逃脱闭包,因此我们可以使用print
:
withoutActuallyEscaping
将闭包铸造为自己的类型也会使闭包转义。这是因为func executetwice(operation:() -> Void) {
withoutActuallyEscaping(operation) {
print($0)
}
operation()
}
是一个“相当复杂”的表达式,其产生类型为operation as () -> Void
的值。所谓“相当复杂”,是指它足够复杂,以至于在将其传递给非转义参数时,编译器不会费心检查您正在强制转换的内容是否确实在转义,因此它假定所有强制转换都在转义。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。