在Kotlin中是'a?.let {}?:run {}`惯用语?

And*_*wka 8 kotlin kotlin-null-safety

我在SO帖子中看到了以下评论,我很好奇:

为什么不使用if进行空检查?a?.let{} ?: run{}只适用于极少数情况,否则它不是惯用的 - voddan 2016年5月15日在7:29 最好的方法来检查kotlin?

为什么这种结构"在极少数情况下才适用"?
Kotlin的首席工程师说,

运行允许您在elvis运营商的右侧使用多个语句 /sf/answers/3586938841/

虽然我承认实际上并不认可它是惯用的.这两个帖子似乎都来自备受推崇的SO Kotlin撰稿人.
启发原始评论的帖子提到let表达的一部分是重要的,如果a是可变的.在这种情况下,你需要a?.let{} ?: run{}而不是if{} else {}.

我发现我喜欢"让猫王跑"的结构.在大多数情况下我应该避免吗?
感谢您的任何见解.

Tim*_*Tim 6

在这种情况下,您需要一个?.let {}?:run {}而不是if {} else {}

不,你可以省略的部分运行run { statement }和使用a?.let{} ?: statement

在大多数情况下应该避免使用吗?

需要时应使用它。例如,当您想在那种情况下运行多个语句时。需要指出的是,这种情况很少见。通常,您会在Elvis运算符的右侧仅看到一条语句。
当然,当您不需要它时也不要使用它。保持代码简单。

  • `run`基本上可以确保elvis运算符在空检查失败后运行的语句超过一个语句的地方可用(如果在空检查后涉及到几行代码,这很有用) (4认同)
  • 请记住,有一个警告。如果let块返回的内容为null,则elvis运算符之后的语句将运行,因此在这种情况下,可以执行let和run。 (4认同)
  • @mhswtf 哦,是的,很好。我赞成您的评论以提高知名度 (2认同)

kev*_*ost 6

这是危险混为一谈foo?.let { bar(it) } ?: baz()if (foo != null) bar(foo) else baz()

说你有一个功能: fun computeElements(): List<Int>? = emptyList()

考虑以下代码:

val maxElement = computeElements()?.let { it.max() } ?: return
println("Max element was $maxElement")
Run Code Online (Sandbox Code Playgroud)

相比:

val list: List<Int>? = computeElements()
val maxElement = if (list != null) list.max() else return
println("Max element was $maxElement")
Run Code Online (Sandbox Code Playgroud)

您可能会认为这是两种等效形式。但是,如果同时运行两者,您将看到前者不会将任何内容输出到stdout!

这是因为it.max()返回null一个空列表(因为没有max元素),这导致对Elvis表达式的右侧求值,因此该函数return较早。

简而言之,?.let { ... } ?: ... 允许评估“ if-else”的两个分支,这很危险。除了这种形式不可读(if-else普遍理解,let-run不是)之外,还可能发生细微的错误。