Null-coalescing out参数会发出意外警告 [英] Null-coalescing out parameter gives unexpected warning

查看:60
本文介绍了Null-coalescing out参数会发出意外警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用此构造:

var dict = new Dictionary<int, string>();
var result = (dict?.TryGetValue(1, out var value) ?? false) ? value : "Default";

我收到一条错误消息,说 CS0165使用了未分配的局部变量'value',这不是我期望的. value 如何可能未定义?如果字典为null,则内部语句将返回 false ,这将使外部语句的值为false,并返回 Default .

I get an error saying CS0165 use of unassigned local variable 'value' which is not what I expect. How could value possibly be undefined? If the dictionary is null the inner statement will return false which will make the outer statement evaluate to false, returning Default.

我在这里想念什么?只是编译器无法完全评估该语句吗?还是我以某种方式搞砸了?

What am I missing here? Is it just the compiler being unable to evaluate the statement fully? Or Have I messed it up somehow?

推荐答案

您的分析是正确的.这不是编译器进行的分析,因为编译器进行C#规范所需的分析.该分析如下:

Your analysis is correct. It is not the analysis the compiler makes, because the compiler makes the analysis that is required by the C# specification. That analysis is as follows:

  • 如果 condition?conequence:alternative 表达式的条件是编译时常量 true ,则该替代分支将不可用;否则,该分支将无法访问.如果 false ,则结果分支不可达;否则,两个分支都是可以到达的.

  • If the condition of a condition?consequence:alternative expression is a compile-time constant true then the alternative branch is not reachable; if false, then the consequence branch is not reachable; otherwise, both branches are reachable.

在这种情况下,条件不是恒定的,因此结果和替代方法都是可以实现的.

The condition in this case is not a constant, therefore the consequence and alternative are both reachable.

局部变量 value ,因此没有明确分配 value 达到后果时.

local variable value is only definitely assigned if dict is not null, and therefore value is not definitely assigned when the consequence is reached.

但是后果是必须明确分配 value

But the consequence requires that value be definitely assigned

所以这是一个错误.

编译器不如您聪明,但是它是C#规范的准确实现.(请注意,我没有在此处勾画出这种情况的其他特殊规则,其中包括谓词,例如在真表达式后确定赋值",等等.有关详细信息,请参见C#规范.)

The compiler is not as smart as you, but it is an accurate implementation of the C# specification. (Note that I have not sketched out here the additional special rules for this situation, which include predicates like "definitely assigned after a true expression" and so on. See the C# spec for details.)

顺便说一句,C#2.0编译器太聪明了.例如,如果对于某些int局部 x 具有类似 0 * x == 0 的条件,它将得出无论 x 是",并将替代分支标记为不可访问.从与现实世界相匹配的角度来看,这种分析是正确的,但从C#规范明确指出仅对编译时常量进行推论,并同样明确地指出涉及变量不是恒定.

Incidentally, the C# 2.0 compiler was too smart. For example, if you had a condition like 0 * x == 0 for some int local x it would deduce "that condition is always true no matter what the value of x is" and mark the alternative branch as unreachable. That analysis was correct in the sense that it matched the real world, but it was incorrect in the sense that the C# specification clearly says that the deduction is only to be made for compile-time constants, and equally clearly says that expressions involving variables are not constant.

请记住,这件事的目的是发现错误,更有可能的是什么?有人写了 0 * x == 0?foo:bar 是否打算具有"always foo "的含义,或者是他们无意中写了一个bug?我已修复了编译器中的错误,此后此错误已严格符合规范.

Remember, the purpose of this thing is to find bugs, and what is more likely? Someone wrote 0 * x == 0 ? foo : bar intending that it have the meaning "always foo", or that they've written a bug by accident? I fixed the bug in the compiler and since then it has strictly matched the specification.

在您的情况下,没有错误,但是代码太复杂而无法编译器进行分析,因此可能也太复杂以至于无法让人进行分析.看看是否可以简化它.我可能会做的是:

In your case there is no bug, but the code is too complicated for the compiler to analyze, so it is probably also too complicated to expect humans to analyze. See if you can simplify it. What I might do is:

public static V GetValueOrDefault<K, V>(
  this Dictionary<K, V> d,
  K key,
  V defaultValue)
{
    if (d != null && d.TryGetValue(key, out var value))
      return value;
    return defaultValue;
}
…
var result = dict.GetValueOrDefault(1, "Default");

目标应该是使呼叫站点更具可读性;我认为我的呼叫站点比您的呼叫站点更具可读性.

The goal should be to make the call site readable; I think my call site is considerably more readable than yours.

这篇关于Null-coalescing out参数会发出意外警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆