Dart 空安全 - 以空安全的方式从地图中检索值
Dart null safety - retrieving value from map in a null safe way
我有类似于此示例代码的代码(没关系,它没有意义):
void foo(Map<int, String> myMap) {
String s = myMap[1];
}
dart 分析器警告我关于行 String s = myMap[1];
的警告如下:
A value of type 'String?' can't be assigned to a variable of type
'String'. Try changing the type of the variable, or casting the
right-hand type to 'String'.
我看到发生这种情况是因为从映射中检索值可能会导致 null
。为什么以下代码片段会给我同样的警告?
void foo(Map<int, String> myMap) {
if (myMap.containsKey(1)) {
String s = myMap[1];
}
}
问题是编译器不知道 map 的方法 containsKey 确实知道。
从理论上讲,您可以传递一些具有 containsKey 的奇怪 Map 实现,它除了检查值是否存在之外还做其他事情。
编译器只有在 100% 确定该值可能不为 null 时才会产生警告。
警告完全基于操作的类型。 Map<K,V>
return 的 operator []
是 V?
,所以它可能是 null
。
类型系统不知道键是否在映射中,甚至不知道映射 是什么 .
您调用另一个方法,这意味着 return 值不会 null
不会更改类型,并且编译器不会得到该暗示。
感谢您的回答。我对尝试使用 myMap[key]
不存在的键会引发错误的语言很感兴趣。在这种情况下,一种可能的模式是首先检查密钥是否存在(尽管这在多线程代码中可能会有问题)。但是这里没有必要进行这样的检查——可以简单地测试值是否不是 null
.
void foo(Map<int, String> myMap) {
if (myMap[1] != null) {
String s = myMap[1];
}
}
在 dartlang github https://github.com/dart-lang/sdk/issues/44444 上看到关于这些内容的很好的解释。
也是 null savety https://dart.dev/null-safety/faq#how-do-i-signal-that-the-return-value-from-a-map-is-non-nullable
的官方常见问题解答
问题:
来自docs:
The index [] operator on the Map class returns null if the key isn’t present. This implies that the return type of that operator must be nullable.
看看下面的代码。由于 Map
中缺少键 b
,map['b']
returns null
并将其值分配给 int
会导致 runtime
错误,如果这已经通过静态分析。
Map<String, int> map = {'a': 1};
int i = map['b']; // Error: You can't assign null to a non-nullable field.
解决方案:
使用??
并提供默认值(推荐)
int i = map['b'] ?? 0;
使用 Bang !
运算符。
int i = map['b']!; // Caution! It causes runtime error if there's no key.
最好的方法是您可以创建地图的扩展。此外,您可以在找不到键时传递一个可选值。这种风格基本上Python like get on dictonary.
dynamic get(String key, {dynamic opt}) {
if (this.containsKey(key)) {
return this[key];
}
return opt;
}
}
现在在不同的文件中,您可以导入并使用它。
dynamic val = map.get('my_key', opt: 'other_value');
我有类似于此示例代码的代码(没关系,它没有意义):
void foo(Map<int, String> myMap) {
String s = myMap[1];
}
dart 分析器警告我关于行 String s = myMap[1];
的警告如下:
A value of type 'String?' can't be assigned to a variable of type 'String'. Try changing the type of the variable, or casting the right-hand type to 'String'.
我看到发生这种情况是因为从映射中检索值可能会导致 null
。为什么以下代码片段会给我同样的警告?
void foo(Map<int, String> myMap) {
if (myMap.containsKey(1)) {
String s = myMap[1];
}
}
问题是编译器不知道 map 的方法 containsKey 确实知道。
从理论上讲,您可以传递一些具有 containsKey 的奇怪 Map 实现,它除了检查值是否存在之外还做其他事情。
编译器只有在 100% 确定该值可能不为 null 时才会产生警告。
警告完全基于操作的类型。 Map<K,V>
return 的 operator []
是 V?
,所以它可能是 null
。
类型系统不知道键是否在映射中,甚至不知道映射 是什么 .
您调用另一个方法,这意味着 return 值不会 null
不会更改类型,并且编译器不会得到该暗示。
感谢您的回答。我对尝试使用 myMap[key]
不存在的键会引发错误的语言很感兴趣。在这种情况下,一种可能的模式是首先检查密钥是否存在(尽管这在多线程代码中可能会有问题)。但是这里没有必要进行这样的检查——可以简单地测试值是否不是 null
.
void foo(Map<int, String> myMap) {
if (myMap[1] != null) {
String s = myMap[1];
}
}
在 dartlang github https://github.com/dart-lang/sdk/issues/44444 上看到关于这些内容的很好的解释。 也是 null savety https://dart.dev/null-safety/faq#how-do-i-signal-that-the-return-value-from-a-map-is-non-nullable
的官方常见问题解答问题:
来自docs:
The index [] operator on the Map class returns null if the key isn’t present. This implies that the return type of that operator must be nullable.
看看下面的代码。由于 Map
中缺少键 b
,map['b']
returns null
并将其值分配给 int
会导致 runtime
错误,如果这已经通过静态分析。
Map<String, int> map = {'a': 1};
int i = map['b']; // Error: You can't assign null to a non-nullable field.
解决方案:
使用
??
并提供默认值(推荐)int i = map['b'] ?? 0;
使用 Bang
!
运算符。int i = map['b']!; // Caution! It causes runtime error if there's no key.
最好的方法是您可以创建地图的扩展。此外,您可以在找不到键时传递一个可选值。这种风格基本上Python like get on dictonary.
dynamic get(String key, {dynamic opt}) {
if (this.containsKey(key)) {
return this[key];
}
return opt;
}
}
现在在不同的文件中,您可以导入并使用它。
dynamic val = map.get('my_key', opt: 'other_value');