Dart:如何正确处理null-safety?



我已经将我的项目升级为null-safety,这有点令人困惑,因为如果我包装成

if(someObject.field != null) { 
doSomething(someObject.field);  // error, can't assign String? to String
}

需要非空属性的方法调用,并且我试图传递的变量是空的,然后我得到一个类型错误,我不能将可空值赋给非空类型。

但是当我做的时候

String? someObjectField = someObject!.field;
if(someObjectField != null) { 
doSometing(someObjectField); // Can assign
}

运行正常

doSomething = (String foo) {}

例如:

class Person {
final String name;
Person(this.name);

}
Function test = () {
Map<String, String?> pers = {
'name': 'John',
};
if(pers['name'] != null) {
Person(pers['name']); // Error, even if it will be never executed
Person(pers['name'] as String); // no error
Person(pers['name']!); // no error
}

};

如果我这样做:

if (widget.event != null && widget.event.featuredImage != null)

然后它在第二个语句中抱怨接收器(widget.event)可以为空,我需要使用!,但第二个语句不应该执行,它不应该导致运行时异常。

所以我需要把它修改为:

if (widget.event != null && widget.event!.featuredImage != null)

但是当我尝试在Flutter中使用嵌套小部件时,即使我使用if作为包装器,我仍然需要在任何地方添加!

Stack(
children: [
// Add Container with image only when event and futured image are not null
if (widget.event != null && widget.event!.featuredImage != null) ...[
Container(
height: 250,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(widget.event!.featuredImage!), // here i Need to use ! to satisfy the compiler
),
),
),
],
],
)

或者,我可以将变量提取到另一个String? image = widget.event!.featuredImage中,然后将if语句修改为if(image != null),并使用像NetworkImage(image)这样的小部件,它按预期工作。

与TypeScript相比,它会检测我是否在上面的条件中检查了null,这对我来说毫无意义。

长话短说,即使我检查null值渲染/不渲染组件,我仍然需要使用!

有什么明显的我错过了吗?

提前谢谢你

既然你把它和TypeScript比较了,是的,你错过了一些东西。

Typescript是一团乱麻,只能在非常有限的环境中工作,而且"works"被严重夸大了。例如,你可以在typescript中写一个功能它接受一个字符串,然后在运行时发现它实际上不是一个字符串,很意外,它是一个完全不同的类型。JavaScript的乐趣。调用TypeScript "type safe"与JS相比是正确的,与实际编译语言相比是荒谬的。

因此,您错过了Dart编译器可以保证一旦您检查它,它就不为空的事实。要做到这一点,它需要额外的约束。例如,可以让getter在每次调用时都返回不同的值。例如,根据getter的代码,您的调用在第一次和第二次调用之间很容易返回不同的值。或者您可以使用继承和多态性来构建一些更有问题的结构。这里有一个有趣的例子。因此,您需要有一个局部变量,保证具有相同的值,除非显式更改。

您的if (widget.event != null && widget.event.featuredImage != null)示例可以很容易地修改为:

final image = widget?.event?.featuredImage;
Stack(
children: [
// Add Container with image only when event and futured image are not null
if (image != null) ...[
Container(
height: 250,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(image), 
),
),
),
],
],
)

是的,你必须实现一些微小的逻辑,你不能只是把?!放在你的代码上,它就像以前一样运行。但一旦你理解了逻辑上的小变化是什么,就很容易了。

相关内容

  • 没有找到相关文章

最新更新