英文:
Null Assertions in null-safe mode and How to Avoid If Possible
问题
学习Dart并使用dart_code_metrics确保我写的代码符合期望。其中一个启用的规则是avoid-non-null-assertion。
请注意,下面的代码是为了重现在一个较大的代码库中遇到的问题,其中unitString的值是从JSON文件中获取的。因此,程序无法控制JSON文件中指定的内容。
从pubspec.yaml中:
environment:
sdk: '>=2.15.0 <3.0.0'
// ignore_for_file: avoid_print
import 'package:qty/qty.dart';
void main() {
const String unitString = 'in';
// 如果unitString不是长度单位,则unit.Width返回null。
if (Length().unitWith(symbol: unitString) == null) {
print('不支持单位 $unitString。');
} else {
// 使用!会触发避免非空断言的警告。
final Unit<Length>? units = Length().unitWith(symbol: unitString)!;
final qty = Quantity(amount: 0.0, unit: units!);
print('Qty = $qty');
}
}
如果我不使用!,那么会得到以下类型错误:
类型为'Unit<Length>?'的值无法赋给类型为'Unit<Length>'的变量。
尝试更改变量的类型,或将右侧的类型转换为'Unit<Length>'。
将右侧类型转换为 Unit<Length>
会修复上述错误,但在实例化Quantity()
时会引发新的错误,因为构造函数需要 Unit<Length>
而不是 Unit<Length>?
。我假设有解决办法,但我是Dart的新手,无法构造出正确的搜索查询来找到答案。
我该如何修改示例代码以使Dart和dart_code_metrics满意?
英文:
Learning Dart and using dart_code_metrics to ensure that I write code that meets expectations. One of the rules that is active is avoid-non-null-assertion.
Note, the code below was created to recreate the problem encountered in a larger code base where the value of unitString is taken from a JSON file. As such the program cannot control what is specified in the JSON file.
From pubspec.yaml
environment:
sdk: '>=2.15.0 <3.0.0'
// ignore_for_file: avoid_print
import 'package:qty/qty.dart';
void main() {
const String unitString = 'in';
// unit.Width returns null if unitString is not a unit of Length.
if (Length().unitWith(symbol: unitString) == null) {
print('units $unitString not supported.');
} else {
// The following line triggers avoid-non-null-assertion with the use of !.
final Unit<Length> units = Length().unitWith(symbol: unitString)!;
final qty = Quantity(amount: 0.0, unit: units);
print('Qty = $qty');
}
}
If I don't use ! then I get the following type error:
A value of type 'Unit<Length>?' can't be assigned to a variable of type 'Unit<Length>'.
Try changing the type of the variable, or casting the right-hand type to 'Unit<Length>'.
Casting the right-hand side to
Unit<Length>
fixes the above error but cause a new error when instantiating Quantity() since the constructor expects
Unit<Length>
and not
Unit<Length>?
I assume there is an solution but I'm new to Dart and cannot formulate the correct search query to find the answer.
How can I modify the sample code to make Dart and dart_code_metrics happy?
答案1
得分: 0
你检查在使用值之前检查null
的想法是好的,只是没有正确实现。Dart会在你使用if
检查null
时自动将可空类型提升为非空类型,但在这种情况下,你需要使用临时变量。
void main() {
const String unitString = 'in';
//使用临时变量,你可以指定类型而不仅仅使用final
final temp = Length().unitWith(symbol: unitString);
if (temp == null) {
print('单位 $unitString 不受支持。');
} else {
final Unit<Length> units = temp;
final qty = Quantity(amount: 0.0, unit: units);
print('Qty = $qty');
}
}
基本原因是,当你第一次调用unitWith
函数并发现它不为null
时,不能保证再次调用时它仍然会返回非空值。我认为有另一个更详细解释这一点的SO问题,但我找不到了。
英文:
Your idea of checking for null
before using a value is good, it's just not implemented correctly. Dart does automatically promote nullable types to non-null ones when you check for null
with an if
, but in this case you need to use a temporary variable.
void main() {
const String unitString = 'in';
//Use a temp variable, you could specify the type instead of using just using final
final temp = Length().unitWith(symbol: unitString);
if (temp == null) {
print('units $unitString not supported.');
} else {
final Unit<Length> units = temp;
final qty = Quantity(amount: 0.0, unit: units);
print('Qty = $qty');
}
}
The basic reason for that when you call your unitWith
function and see that it's not null
the first time, there's no guarantee that the when you call it again that it will still return a non-null value. I think there's another SO question that details this better, but I can't seem to find.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论