Kotlin:在“ null”作弊时如何使用其他条件让let块使用

时间:2019-07-10 16:52:22

标签: kotlin null

我正在用代码中的let块替换所有空检查,

1。 空检查的代码示例:

if(someValue != null){//run if someValue is not null}
else {//run if someValue is null}

2。 如果进行空检查,则使用let-run块后的代码库,

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?.run {
//This code block should run only when if someValue is null, like else condition
}

let-run块现在存在的问题是,即使someValue不为null,两个代码块都在运行。因此,我无法将代码示例1中if-else条件的行为复制到代码示例2中的run-let条件。

预期的行为是根据value为null或not null来执行let或run代码块。

5 个答案:

答案 0 :(得分:5)

  

我正在用代码中的let块替换所有空检查

这里的第一个问题是,为什么?与常规的if-else结构相比,这对您来说更具可读性吗?我通常会出于重构的考虑而警惕重构。

第二个考虑要重要得多:您正在进行的转换不等同于原始代码,您实际上是通过此更改来修改行为。请执行以下代码:

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
    foo(someSafeValue)
    bar(someSafeValue)
} ?: run {
    println("shouldn't happen if someValue != null")
}

您希望run块仅在someValue == null时执行,但是实际上并不是唯一的情况。整个someValue?.let { ... }表达式不仅可以在null本身为someValue时生成null值,而且还可以在传递给let的块返回null的情况下生成bar()值。 。在这种情况下,如果null函数调用导致run,则if-else语句将在之后执行,因此运行您认为是 public void importFile() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*"); startActivityForResult(intent, 7); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub switch (requestCode) { case BROWSE_FILE: if (resultCode == RESULT_OK) { String PathHolder = data.getData().getPath(); Toast.makeText((DashboardsActivity) getContext(), PathHolder, Toast.LENGTH_LONG).show(); readTextFileType(PathHolder); mergeArr(); tableCalculation(); setRecyclerviewAfterImport(); } break; } } private void readTextFileType(String uri) { int count = 0; String line; String characterAtThisPosition; StringBuffer stringBuffer = new StringBuffer(); try { BufferedReader reader = new BufferedReader(new FileReader(uri)); Log.i("", "open text file - content" + "\n"); while ((line = reader.readLine()) != null) { Log.i("", line + "\n"); if (line.equalsIgnoreCase("MD(ft) Inclination(?) Azimuth(?)")) { // call method to extract data from file type 1 isReadyToFill = false; extractDataFromFileTypeOne(uri); return; } else if (line.equalsIgnoreCase(" MD Inclin Azimuth")) { extractDataFromFileTypeTwo(uri); // call method to extract data from file type 2 return; } else if (line.equalsIgnoreCase(" Measured Incl Drift True Vertical CLOSURE CLOSURE Dogleg ")) { // call method to extract data from file type 3 extractDataFromFileTypeThree(uri); return; } } reader.close(); } catch (Exception e) { e.printStackTrace(); } } 的两个分支声明。

答案 1 :(得分:2)

来源-kotlinlang.org

  • ?。执行安全调用(如果接收者为非null,则调用方法或访问属性)
  • ?:如果左侧值为null(elvis运算符),则采用右侧值

更改将解决此问题,

下面的代码库将基于空检查运行let或run块。

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?:run {
//This code block will run only when if someValue is null, like else condition
}

答案 2 :(得分:0)

您可以像这样创建扩展功能

fun <T> T?.whenNull(block: () -> Unit) = this ?: block()

然后您这样称呼

somevalue?.let { safeSomeValue ->
    // TODO
}.whenNull {
    // execute when someValue is null
}

答案 3 :(得分:0)

给出zsmb13的答案所涉及的非常具体的示例:

val someValue = 0
someValue?.let { safeSomeValue->
    println("then")
    null
} ?: run {
    println("else")
}

同时打印thenelse。您可以使用also而不是let来解决此问题:

val someValue = 0
someValue?.also { safeSomeValue->
    println("then")
    null
} ?: run {
    println("else")
}

将仅打印then。阅读https://kotlinlang.org/docs/reference/scope-functions.html并找出原因,并证明它确实总是与原始if ... else等效,可能会很有用。但是我也同意zsmb13,这可能是个坏主意。

答案 4 :(得分:0)

您可以编写两个扩展函数,例如:“ifSafe”和“ifNull”,它们可以单独使用或链接在一起以模仿 if/else 模式:

fun <T> T?.ifSafe(block: (t:T?) -> Unit) = if (this!=null) block(this) else this
fun Any?.ifNull(block: () -> Unit?) = if (this==null) block().also{return null} else this

fun main() {

    var someValue = 4
    var nullValue = null
    
    someValue.ifSafe { safeSomeValue ->
        println("someValue: "+safeSomeValue.toString())
        null
    }.ifNull{
        println("someValue is null.")
    }
    
    someValue.ifNull{
        println("someValue is null.")
    }.ifSafe{ safeSomeValue ->
        println(safeSomeValue)
    }
    
    nullValue.ifNull{
         println("nullValue is null.")
    }
    
}