飞镖:警告“信息:此函数的返回类型为'int',但不以return语句结尾”)

时间:2019-12-15 16:14:10

标签: flutter dart

我对以下代码段发出警告,但我不知道为什么。

List<Map<String, int>> callNoInfo = [];

int getCallNo(String phoneNo) {
  callNoInfo.forEach((item) {
    if (item.containsKey(phoneNo)) {
      return item[phoneNo];
    }
  });
  return 0;
}

警告是:

This function has a return type of 'int', but doesn't end with a return statement. (missing_return at [project_name] lib\helper\call_no.dart:35)

谁能告诉我为什么会这样?预先感谢

2 个答案:

答案 0 :(得分:3)

forEach方法中,您正在创建lambda函数而未显式定义返回类型,因此Dart试图从return语句中推断出它。如果我们从forEach方法中提取函数,那么可能有助于了解我的意思:

...
(item) {
  if (item.containsKey(phoneNo)) {
    return item[phoneNo];
  }
}
...

该函数包含一个return语句,该语句返回item[phoneNo],它是一个int值。 Dart使用此推断出此lambda函数的返回类型为int。但是,现在知道了这一点,它还注意到,如果代码执行未进入if块,则没有return语句与{{1 }}条件。如果else对象不包含键if,该方法将返回什么?

(答案是该方法将隐式返回item,这就是为什么该消息只是警告而不是编译器错误的原因,但出现警告是因为您可能不是故意这样做的。开发人员,也可以帮助您使代码减少对隐形Dart运行时魔术的依赖。)

要解决此问题,在phoneNo块之外还需要另一个null

return

但是,现在有另一个问题。列表上的if方法具有以下签名:

...
(item) {
  if (item.containsKey(phoneNo)) {
    return item[phoneNo];
  }
  return 0;
}
...

实际上,有两个问题。首先,作为参数传递的方法需要具有返回类型forEach,而forEach(void f(E element)) → void 方法本身也具有返回类型void。这意味着您根本无法从forEach方法中返回值。

关于void方法的事情是,它旨在遍历集合并处理其中的每个值。这并不是要(也不能)搜索值并在找到后返回它。此外,迭代是详尽无遗的,这意味着一旦启动迭代,就无法停止该方法,直到对集合中的每个元素都进行了迭代为止。

正如其他答案所指出的,这就是为什么您真正应该使用forEachforEach循环的原因:

for

(我不确定为什么将for in的返回值分配给List<Map<String, int>> callNoInfo = []; int getCallNo(String phoneNo) { for(var item in callNoInfo) { if (item.containsKey(phoneNo)) { return item[phoneNo]; } } return 0; } 的lambda函数不会出现编译器错误,该方法显然正在请求一个带有int返回类型。但是,如果我不得不猜测,我会说Dart运行时将它们视为兼容并通过简单地丢弃lambda函数的返回值来调和返回类型的差异。)

答案 1 :(得分:-2)

forEach循环内的if语句没有其他情况。即使最后可能会有一个,但仍然希望到处都是这样。

List<Map<String, int>> callNoInfo = [];
int getCallNo(String phoneNo) {
  callNoInfo.forEach((item) {
    if (item.containsKey(phoneNo)) {
      return item[phoneNo];
    }
    // you don't have a case for here since it's in a callback
  });
  return 0;
}

但是,您可以使用for in循环来做到这一点:

List<Map<String, int>> callNoInfo = [];
int getCallNo(String phoneNo) {
  for (var item in callNoInfo) {
    if (item.containsKey(phoneNo)) {
      return item[phoneNo];
    }
  }
  return 0;
}