如何进行空安全断言以避免在 Flutter 中使用空检查 (!) 或条件 (?) 运算符?
How can I make null-safety assertions to avoid using null check (!) or conditional (?) operators in Flutter?
当我在 if (x != null)
语句中使用它时,Dart 编译器不理解变量 不能为 null。它仍然需要使用条件 ?
或空检查 !
运算符来访问变量的字段或方法之一。
这是一个例子:
String? string;
void test() {
if (string != null) {
print(string.length);
}
}
这会产生一个编译时错误并表示
The property 'length' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!').
然而,接收者实际上不能为空,因为它被 if (string != null)
块包裹着。使用 string?.length
或 string!.length
访问字段工作正常,但当我需要使用变量的不同字段或方法时可能会造成混淆。
String? string;
void test() {
if (string != null) {
print(string.length);
print(string.isNotEmpty);
print(string.trim());
print(string.contains('x'));
}
}
所有这些语句都会引发相同的错误。我也试过放置 assert(string != null);
但编译器仍然不明白该字符串不为空。
举个更复杂的例子;
User? user;
@override
Widget build(BuildContext context) {
if (user == null) {
return Text('No user available');
} else {
return buildUserDetails();
}
}
Widget buildUserDetails() {
return Column(
children: [
Text(user.name),
Text(user.email),
],
);
}
这仍然是编译器的问题。
这些是为了健全的零安全。这就是为什么每当你开始调用一个函数/访问它时,通过使用确保变量不为空!或使用 ?.
为 null 提供其他情况
假设以下情况:
if (string != null) {
string=null; // Or through other function xyx() {string=null;} string becomes null then your if condition is void
print(string.length);
print(string.isNotEmpty);
print(string.trim());
print(string.contains('x'));
}
// Still sound null safety that's why above is not allowed
if (string != null) {
string=null; // Or through other function xyx() {string=null;} string becomes null then your if condition is void
print(string!.length);
print(string!.isNotEmpty);
print(string!.trim());
print(string!.contains('x'));
}
所以为了健全的空安全需要在访问字符串之前检查它是否不为空
根据您的意见,您需要将此可空字符串分配给不可空字符串(~isdatablank~ 表示字符串为空)并继续
String? string;
String s=string??"~isdatablank~";
if (s != "~isdatablank~") {
print(s.length);
print(s.isNotEmpty);
print(s.trim());
print(s.contains('x'));
}
However, the receiver actually can't be null since it's wrapped
这个假设是完全错误的。
你的变量是一个全局变量和你程序的任何其他部分,通过multi-threading或其他恶作剧可以滑动在 if
和下一行之间 更改 变量。
这就是为什么只有 局部变量 可以提升为它们的 non-null 等价物,当编译器证明它们在某些代码执行分支中不能为空时,例如 if
.
下面的代码会工作得很好,因为你操作的是编译器可以确定不会被外部操作改变的局部变量:
String? string;
void test() {
final local = string;
if (local != null) {
// here, local was promoted from "string?" to "string"
// since the "if" makes sure it is not null AND
// the variable is not accessible to anything but this
// function, so it cannot be changed from the outside
// and is contrained to the sequential flow of this method.
print(local.length);
}
}
当我在 if (x != null)
语句中使用它时,Dart 编译器不理解变量 不能为 null。它仍然需要使用条件 ?
或空检查 !
运算符来访问变量的字段或方法之一。
这是一个例子:
String? string;
void test() {
if (string != null) {
print(string.length);
}
}
这会产生一个编译时错误并表示
The property 'length' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!').
然而,接收者实际上不能为空,因为它被 if (string != null)
块包裹着。使用 string?.length
或 string!.length
访问字段工作正常,但当我需要使用变量的不同字段或方法时可能会造成混淆。
String? string;
void test() {
if (string != null) {
print(string.length);
print(string.isNotEmpty);
print(string.trim());
print(string.contains('x'));
}
}
所有这些语句都会引发相同的错误。我也试过放置 assert(string != null);
但编译器仍然不明白该字符串不为空。
举个更复杂的例子;
User? user;
@override
Widget build(BuildContext context) {
if (user == null) {
return Text('No user available');
} else {
return buildUserDetails();
}
}
Widget buildUserDetails() {
return Column(
children: [
Text(user.name),
Text(user.email),
],
);
}
这仍然是编译器的问题。
这些是为了健全的零安全。这就是为什么每当你开始调用一个函数/访问它时,通过使用确保变量不为空!或使用 ?.
为 null 提供其他情况假设以下情况:
if (string != null) {
string=null; // Or through other function xyx() {string=null;} string becomes null then your if condition is void
print(string.length);
print(string.isNotEmpty);
print(string.trim());
print(string.contains('x'));
}
// Still sound null safety that's why above is not allowed
if (string != null) {
string=null; // Or through other function xyx() {string=null;} string becomes null then your if condition is void
print(string!.length);
print(string!.isNotEmpty);
print(string!.trim());
print(string!.contains('x'));
}
所以为了健全的空安全需要在访问字符串之前检查它是否不为空
根据您的意见,您需要将此可空字符串分配给不可空字符串(~isdatablank~ 表示字符串为空)并继续
String? string;
String s=string??"~isdatablank~";
if (s != "~isdatablank~") {
print(s.length);
print(s.isNotEmpty);
print(s.trim());
print(s.contains('x'));
}
However, the receiver actually can't be null since it's wrapped
这个假设是完全错误的。
你的变量是一个全局变量和你程序的任何其他部分,通过multi-threading或其他恶作剧可以滑动在 if
和下一行之间 更改 变量。
这就是为什么只有 局部变量 可以提升为它们的 non-null 等价物,当编译器证明它们在某些代码执行分支中不能为空时,例如 if
.
下面的代码会工作得很好,因为你操作的是编译器可以确定不会被外部操作改变的局部变量:
String? string;
void test() {
final local = string;
if (local != null) {
// here, local was promoted from "string?" to "string"
// since the "if" makes sure it is not null AND
// the variable is not accessible to anything but this
// function, so it cannot be changed from the outside
// and is contrained to the sequential flow of this method.
print(local.length);
}
}