我正在用代码中的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代码块。
答案 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
用??更改?将解决此问题,
下面的代码库将基于空检查运行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")
}
同时打印then
和else
。您可以使用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.")
}
}