VS调试问题,谁能帮我解释以下内容?

9
一个C#代码片段。
var isTrue = (new List<int>{1,2,3} is IEnumerable<object>);

我在代码执行中得到了结果false, 但当我将该代码复制到WATCH窗口中时,结果是true


1
我猜测 IEnumable 是一个打字错误? - casiosmu
1
@ManfredRadlwimmer 当然,这是代码执行行为的正确答案。这个问题有趣的部分是:为什么调试器监视窗口不同意?我可以重现这个问题。 - René Vogt
这显然是调试器中的一个错误。原因可能是CLR和C#没有实际执行相同的规则,但这种说法似乎最多也只是不可靠的,而且我现在没有时间检查确切的CLR差异规则以及它们是否与C#完全匹配。显而易见的是,至少就C#而言,当涉及到值类型的泛型类型时,类型方差是不允许的,所以调试器是错的。 - InBetween
小更新:甚至 new List<int>{1,2,3} as IEnumerable<object> 也可以工作 o_O - Manfred Radlwimmer
我认为这与https://developercommunity.visualstudio.com/content/problem/142642/inconsistent-result-of-covariance-for-primitive-an.html有关,并且他们似乎正在对此进行调查。 - Dzyann
显示剩余6条评论
1个回答

1
这不是完整的答案(我不知道为什么会出现这个错误),但它可以解释调试器的不稳定行为,显然存在缺陷。
首先:C#禁止(而且据我所知,CLR也是如此)涉及值类型的类型变异;只有当所涉及的类型之间存在保持标识的转换时,才允许变异,否则会失败(值类型不存在保持标识的转换)。
object[] oo = new int[] {1, 2, 3}; //will fail
IEnumerable<object> oo = new int[] {1, 2, 3}; //will fail

调试器的立即窗口显然是错误的,new List<int> { 1, 2, 3 }IEnumerable<object> 应该像运行时一样返回 false。为什么它返回 true?因为有一个 bug,就这样。
更令人困惑的是,当 int[] 隐式转换为 IEnumerable<int>List<int> 相同时,new int[] { 1, 2, 3 }IEnumerable<object> 将会正确地返回 false
我发现后者的正确行为唯一的原因是编译器已经用警告标记了那个表达式总是 false,因此编译器分析数组情况的方式不同于任何其他的 IEnumerable

是的,在IDE窗口中有一个可疑类型警告。根据您的话,不稳定是关键因素。 - Raymond He

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接