“参数类型'字符串?' 使用 stdin.readLineSync() 时不能分配给参数类型 'String'"

Bru*_*nça 3 dart

我是飞镖新手。我不知道我犯了什么样的错误,但是这段代码不起作用。是一个简单的代码,只需在终端中读取年龄并说它是未成年人或超过 18 岁。

import 'dart:io'; 

main(){
  print("Entre com a sua idade: ");
  var input = stdin.readLineSync();
  var idade = int.parse(input);

  if(idade >= 18){
    print("É maior de idade");
  }else{
    print("É menor de idade");
  }
}
Run Code Online (Sandbox Code Playgroud)

我得到这个错误:

algoritmo01.dart:15:25: 错误:参数类型“字符串?” 不能分配给参数类型 'String',因为 'String?' 可以为空,而 'String' 不是。var idade = int.parse(input);

jul*_*101 8

欢迎使用飞镖。您所体验的是新的 null 安全功能(随 Dart 2.12.0 引入),默认情况下变量不能包含值 null。这是静态检查的,因此即使在执行程序之前您也会收到错误。

在您的示例中,问题是以下行:

var input = stdin.readLineSync();
Run Code Online (Sandbox Code Playgroud)

如果我们查看手册,我们可以看到此方法具有以下签名:

String? readLineSync (
    {Encoding encoding = systemEncoding,
    bool retainNewlines = false}
) 
Run Code Online (Sandbox Code Playgroud)

https://api.dart.dev/stable/2.12.2/dart-io/Stdin/readLineSync.html

String?意味着它是可空类型,因此允许包含任何字符串或空值。如果类型改为是,String则意味着结果只能是 aString而 never null

这意味着您的变量input现在具有类型String?. 如果您查看示例的第二行,这(在 2.12.0 中引入)是一个问题:

var idade = int.parse(input);
Run Code Online (Sandbox Code Playgroud)

由于 的签名int.parse是:

int parse (

    String source,
    {int? radix,
    @deprecated int onError(
        String source
    )}

) 
Run Code Online (Sandbox Code Playgroud)

https://api.dart.dev/stable/2.12.2/dart-core/int/parse.html

其中需要 a String(因此永远不会是null)。因此,您不能将String?as 参数提供给仅处理String. 相反的情况是被允许的(如果方法需要String?并且你给它一个String)。

那么对于这种情况我们能做些什么呢?那么,你需要处理的情况下,null或者告诉飞镖,它应该只是你的程序崩溃,如果inputnull

所以你可以像这样处理它:

import 'dart:io';

void main() {
  print("Entre com a sua idade: ");
  var input = stdin.readLineSync();
  
  if (input != null) {
    var idade = int.parse(input);

    if (idade >= 18) {
      print("É maior de idade");
    } else {
      print("É menor de idade");
    }
  } else {
    print('Input was null!');
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,即使input技术上仍然是 类型,这也是允许的String?。但是 Dart 可以看到您的if语句将阻止input具有该值,null因此String只要您在此 if 语句中,它就会被“提升” 。

另一种解决方案是告诉达特应该停止抱怨关于静态误差input,只是假设inputString编译代码时:

import 'dart:io';

void main() {
  print("Entre com a sua idade: ");
  var input = stdin.readLineSync()!;
  var idade = int.parse(input);

  if (idade >= 18) {
    print("É maior de idade");
  } else {
    print("É menor de idade");
  }
}
Run Code Online (Sandbox Code Playgroud)

(更改是在!之后添加的readLineSync()

在这种情况下,Dart 将改为添加自己的null-check 并在stdin.readLineSync确实给出null值时使程序崩溃。这是为了确保我们永远不会给出int.parse一个空值,这可能会使您的代码在其他地方崩溃。通过null在我们得到可疑值的地方添加-check,我们可以确保我们快速失败并且在事情不像我们预期的那样的地方失败。

您可以在此处阅读有关 Dart 中空安全的更多信息(也由 Stephen 链接):https : //dart.dev/null-safety/understanding-null-safety

  • 很好又详细的解释! (2认同)