【问题标题】:Detect Recursive calls in C# code检测 C# 代码中的递归调用
【发布时间】:2020-12-27 19:00:40
【问题描述】:

我想在我的代码中查找所有递归调用。

如果我在 Visual Studio 中打开文件,我会在编辑器的左侧看到“递归调用”图标。

我想检查此类调用的整个解决方案。

我使用了 Resharper 命令行工具和 VS 的插件 Resharper - 代码检查,没有运气,这条规则没有应用在他们的规则集中。

有什么方法可以检查整个解决方案 - 我真的不想打开每个文件并检查那个蓝色的“递归调用”图标:)

编辑:我对单级递归感兴趣

【问题讨论】:

  • 您知道这个图标不会出现在多级递归中吗? IE。方法 A 调用 B,而 B 又调用 A 等?
  • 是的,我知道,我只想要单级递归。

标签: c# visual-studio recursion resharper code-analysis


【解决方案1】:

可以使用Mono.Cecil

这是一个简单的LINQPad 程序,演示:

const string AssemblyFilePath = @"path\to\assembly.dll";

void Main()
{
    var assembly = ModuleDefinition.ReadModule(AssemblyFilePath);
    var calls =
        (from type in assembly.Types
         from caller in type.Methods
         where caller != null && caller.Body != null
         from instruction in caller.Body.Instructions
         where instruction.OpCode == OpCodes.Call
         let callee = instruction.Operand as MethodReference
         select new { type, caller, callee }).Distinct();

    var directRecursiveCalls =
        from call in calls
        where call.callee == call.caller
        select call.caller;

    foreach (var method in directRecursiveCalls)
        Debug.WriteLine(method.DeclaringType.Namespace + "." + method.DeclaringType.Name + "." + method.Name + " calls itself");
}

这将输出直接调用自己的方法。请注意,我只处理了Call 指令,我不确定如何正确处理这里的其他调用指令,甚至 if 这甚至是可能的。

警告:请注意,由于我只处理了那条指令,因此只适用于静态编译的调用。

虚拟调用,通过接口调用,只是碰巧回到相同的方法,不会被检测到,为此需要更高级的代码。

【讨论】:

  • 只是澄清一下,以防有人不确定;您不需要 Mono 来执行此操作。在 LinqPad Pro 中,您可以在“查询属性”窗口中添加 NuGet 包“Install-Package Mono.Cecil”。如果您是一个便宜的滑板并且拥有免费版本,那么您需要将 nuget 包下载到另一个临时项目中,然后使用查询属性将其他程序集添加到您的查询中。否则 ModuleDefinition.ReadModule 将没有正确的引用来工作。
  • 我已经下载了github.com/jbevain/cecil/releases 构建并使用上面的代码运行并列出了所有递归调用。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
  • 2010-10-18
  • 2018-08-16
  • 2015-09-10
相关资源
最近更新 更多