Dart的编译器为什么会认为代码可能为null,即使代码明确保证它不会为null?

huangapple go评论55阅读模式
英文:

Why does Dart's compiler believe code might be null when the code guarantees it cannot be?

问题

I'm working through an exercise from this course. This code:

void main() {
  const order = ['pepperoni', 'margherita', 'pineapple'];
  print("Total: ${calculateTotal(order)}");

}

double calculateTotal(List<String> order) {
  var total = 0.0;
  const pizzaPrices = {
    'margherita': 5.5,
    'pepperoni': 7.5,
    'vegetarian': 6.5,
  };
  for (var item in order) {
    if (pizzaPrices[item]!=null) {
    total += pizzaPrices[item];
    } 
  }
  
  return total;
}

Produces the error message The argument type 'double?' can't be assigned to the parameter type 'num'. pointing to the line total += pizzaPrices[item];

total += pizzaPrices[item]! compiles as expected, without errors.

I don't understand why the compiler would need the !, since it already knows pizzaPrices[item] cannot be null.

英文:

I'm working through an exercise from this course. This code:

void main() {
  const order = ['pepperoni', 'margherita', 'pineapple'];
  print("Total: ${calculateTotal(order)}");

}

double calculateTotal(List<String> order) {
  var total = 0.0;
  const pizzaPrices = {
    'margherita': 5.5,
    'pepperoni': 7.5,
    'vegetarian': 6.5,
  };
  for (var item in order) {
    if (pizzaPrices[item]!=null) {
    total += pizzaPrices[item];
    } 
  }
  
  return total;
}

Produces the error message The argument type 'double?' can't be assigned to the parameter type 'num'. pointing to the line total += pizzaPrices[item];

total += pizzaPrices[item]! compiles as expected, without errors.

I don't understand why the compiler would need the !, since it already knows pizzaPrices[item] cannot be null.

答案1

得分: 5

以下是您要翻译的部分:

"The reason is that the [] operator on Map is defined to return a nullable type since if the element you search for are not in the map, the [] operator will return null.

It might look obvious to you, but the compiler cannot know for sure that just because you checked the returned value from pizzaPrices[item] once, it will return the same value again the second time you ask (e.g. in some custom made Map implementation).

A solution is instead to save the value in a local variable which you can then check for null. Dart will in this case promote the variable as expected:

void main() {
  const order = ['pepperoni', 'margherita', 'pineapple'];
  print("Total: ${calculateTotal(order)}");
}

double calculateTotal(List<String> order) {
  var total = 0.0;
  const pizzaPrices = {
    'margherita': 5.5,
    'pepperoni': 7.5,
    'vegetarian': 6.5,
  };
  for (var item in order) {
    final pizzaPrice = pizzaPrices[item];

    if (pizzaPrice != null) {
      total += pizzaPrice;
    }
  }

  return total;
}
英文:

The reason is that the [] operator on Map is defined to return a nullable type since if the element you search for are not in the map, the [] operator will return null.

It might look obvious to you, but the compiler cannot know for sure that just because you checked the returned value from pizzaPrices[item] once, it will return the same value again the second time you ask (e.g. in some custom made Map implementation).

A solution is instead to save the value in a local variable which you can then check for null. Dart will in this case promote the variable as expected:

void main() {
  const order = [&#39;pepperoni&#39;, &#39;margherita&#39;, &#39;pineapple&#39;];
  print(&quot;Total: ${calculateTotal(order)}&quot;);
}

double calculateTotal(List&lt;String&gt; order) {
  var total = 0.0;
  const pizzaPrices = {
    &#39;margherita&#39;: 5.5,
    &#39;pepperoni&#39;: 7.5,
    &#39;vegetarian&#39;: 6.5,
  };
  for (var item in order) {
    final pizzaPrice = pizzaPrices[item];

    if (pizzaPrice != null) {
      total += pizzaPrice;
    }
  }

  return total;
}

huangapple
  • 本文由 发表于 2023年2月19日 01:47:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75495247.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定