静态检测foreach语句中的类型不匹配

本文关键字:类型 不匹配 语句 检测 foreach 静态 | 更新日期: 2023-09-27 18:13:22

我有一个很大的c#代码库,我试图重构和清理其他人的混乱代码。我最近偶然发现了这样一个代码块:

List<Bar> bars = ... ;
...
foreach (Foo foo in bars) { ... }
...
public class Bar
{
    ...
    public static explicit operator Foo() { ... }
}

这个类型不匹配是一个问题。而且,正如您所期望的,代码实际上不能工作:这是一个隐藏在视线中很长时间的错误。

然而,代码是合法的。Visual Studio 2013和ReSharper 2016都没有抱怨这个相当明显的bug:我不得不等到运行时异常才发现代码被破坏了。我宁愿早点知道。

我研究了Visual Studio和ReSharper的选项,试图找到一种方法来让我的工具检测这些类型不匹配:ReSharper的"代码模式"是我能得到的最接近的,虽然它可以识别错误的语法模式,但它不支持足够深入的类型分析来检测错误。

所以有人知道一种方法,使ReSharper静态检测foreach类型不匹配?或者,有人知道有什么工具可以吗?

更新:我最初省略了从BarFooexplicit自定义铸造操作符-那是explicit,请注意,不是implicit。该强制转换操作符的存在似乎对工具检测此问题的能力造成了严重破坏。我已经更新了相关代码以显示该行为。

静态检测foreach语句中的类型不匹配

好吧,见鬼,所以有一个可靠的答案,感谢Eric Lippert的博客。

显然foreach插入了对explicit强制转换操作符的调用,如果有的话。

ReSharper允许这样做是正确的,Visual Studio也是。排序的。(个人而言,我仍然认为ReSharper应该警告它,即使它是合法的。)

引用利伯特先生的几句话来解释:

答案是:foreach循环语义是在泛型添加到语言之前设计的…在泛型的世界中,绝大多数枚举序列现在都是静态类型的,这是一个错误的特性。但是移除它将会是一个很大的破坏性改变,所以我们坚持使用它。

你可能想知道为什么c#编译器在使用泛型的现代代码中不产生警告。当我在c#编译器团队时,我实现了这样一个警告,并在微软的c#代码语料库中进行了尝试。在正确代码中产生的警告数量很大(当有人有动物序列,但通过其他方式知道它们都是长颈鹿)。在正确的代码中频繁发出的警告是糟糕的警告,所以我们选择不添加该功能。

(完整的博客文章可以在这里找到,它既令人失望又令人启发。https://ericlippert.com/2013/07/22/why-does-a-foreach-loop-silently-insert-an-explicit-conversion/)