【发布时间】:2018-04-10 00:12:54
【问题描述】:
在 Kotlin 中,这段代码可以编译:
private fun bar(): Boolean = TODO()
fun works(): Int {
while (true) {
if (bar()) {
return 5
}
}
}
(这是我真实代码的精简示例,用于说明我遇到的问题。)
我实际上需要在这个循环中使用一个文件,并在退出时关闭:
fun openFile(): InputStream = TODO()
fun doesnt_work(): Int {
openFile().use { input ->
while (true) {
if (bar()) {
return 5
}
}
}
} // line 42
这不会编译。我得到错误:
错误:(42, 5) Kotlin: 带有块体 ('{...}') 的函数中需要一个 'return' 表达式
我找到了两种解决此问题的方法,但都有些尴尬。
一种方法是使用变量来保存结果,并在设置后立即从循环中中断:
fun works_but_awkward(): Int {
openFile().use { input ->
val result: Int
while (true) {
if (bar()) {
result = 5
break
}
}
return result
}
}
这在我的真实代码中特别尴尬,因为我有一个嵌套循环,所以我需要使用带标签的中断。
解决此问题的另一种方法是为循环指定一个命名函数:
fun workaround_with_named_function(): Int {
fun loop(input: InputStream): Int {
while (true) {
if (bar()) {
return 5
}
}
}
return openFile().use { loop(it) }
}
这似乎好一点,但我仍然感到惊讶的是,use 抽象是如此泄漏,以至于我无法从循环中提前返回。有没有办法在不那么尴尬的循环中使用use 并提前返回?
【问题讨论】:
-
如果您在 use 块之后返回一个虚拟值,编译器会在您的第一个 doesnt_work() 示例中感到满意,即使它永远不会返回。我建议在discuss.kotlinlang.org 提出这个问题,以便从事该语言/图书馆工作的人们希望看到它或提供更好的答案。
-
请看看我的回答,我认为它看起来比你的解决方法和其他答案都好。
标签: kotlin