You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中程序化获取方法总行数及调用时实际执行行数?

在C#中程序化获取方法总行数与实际执行行数

想要搞定这个需求,我们可以拆成两个核心问题来解决:一是拿到目标方法的总行数,二是追踪它实际执行的代码行数。下面我会结合C#官方提供的API,给你具体的实现方案:


获取方法的总行数

要获取方法的总行数,核心是拿到方法在源码中的起始和结束行号,再计算差值。这里有两种可行的方案:

方案1:通过PDB符号文件读取行号信息

这个方案依赖项目生成的调试符号文件(.pdb),Debug模式默认会生成,Release模式需要在项目设置中勾选"生成调试信息"。我们可以用System.Diagnostics.SymbolStore命名空间的API读取pdb中的行号数据:

using System;
using System.Diagnostics;
using System.Diagnostics.SymbolStore;
using System.Linq;
using System.Reflection;

public static class MethodLineCounter
{
    public static int GetTotalLines(MethodBase method)
    {
        var module = method.Module;
        using var symbolReader = module.SymbolReader;
        
        if (symbolReader == null)
            throw new InvalidOperationException("无法读取符号文件,请确保项目生成了.pdb文件。");

        var methodSymbol = symbolReader.GetMethod(method.MetadataToken);
        var sequencePoints = methodSymbol.GetSequencePoints();
        
        if (sequencePoints.Length == 0)
            return 0;

        // 取所有序列点的起始和结束行,计算总行数
        int startLine = sequencePoints.Min(sp => sp.StartLine);
        int endLine = sequencePoints.Max(sp => sp.EndLine);
        
        return endLine - startLine + 1;
    }
}

方案2:用Roslyn直接解析源码文件

如果你能直接访问方法对应的源码文件,可以用Roslyn(Microsoft.CodeAnalysis.CSharp)解析语法树,直接定位方法的行范围:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System.IO;
using System.Linq;

public static class MethodLineCounter
{
    public static int GetTotalLinesFromSource(string sourceFilePath, string methodName)
    {
        var sourceCode = File.ReadAllText(sourceFilePath);
        var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
        var rootNode = syntaxTree.GetRoot();
        
        var methodNode = rootNode.DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .FirstOrDefault(m => m.Identifier.Text == methodName);
        
        if (methodNode == null)
            throw new ArgumentException($"未找到名为{methodName}的方法");

        var startLine = methodNode.SyntaxTree.GetLineSpan(methodNode.Span).StartLinePosition.Line + 1;
        var endLine = methodNode.SyntaxTree.GetLineSpan(methodNode.Span).EndLinePosition.Line + 1;
        
        return endLine - startLine + 1;
    }
}

追踪实际执行的行数

要记录方法实际跑了哪些行,需要在行执行时触发追踪逻辑。这里提供两种原生实现方案:

方案1:利用DiagnosticSource实现可监听的行追踪

System.Diagnostics.DiagnosticSource是.NET官方提供的诊断API,可以让我们在代码中注入追踪事件,然后在外部监听收集数据。如果想减少手动代码,可以结合Roslyn在编译时自动给每一行插入追踪逻辑(适合大规模场景)。

先看手动注入的简化示例:

using System.Diagnostics;

public class BusinessLogic
{
    private static readonly DiagnosticSource _traceSource = new DiagnosticListener("MethodExecutionTrace");

    public void ProcessData()
    {
        TraceLine(3); // 对应源码行号
        bool condition = true;
        if (condition)
        {
            TraceLine(6);
            TraceLine(7);
            // 其他业务代码
        }
        else
        {
            // 未执行的分支
        }
    }

    private void TraceLine(int lineNumber)
    {
        if (_traceSource.IsEnabled("LineExecuted"))
        {
            _traceSource.Write("LineExecuted", new 
            { 
                MethodName = nameof(ProcessData),
                ExecutedLine = lineNumber 
            });
        }
    }
}

然后在监听端收集执行的行号:

var listener = new DiagnosticListener("MethodExecutionTrace");
listener.SubscribeWithAdapter(new LineExecutionListener());

public class LineExecutionListener
{
    public void OnLineExecuted(KeyValuePair<string, object> payload)
    {
        var data = payload.Value;
        var methodName = data.GetType().GetProperty("MethodName").GetValue(data).ToString();
        var lineNumber = (int)data.GetType().GetProperty("ExecutedLine").GetValue(data);
        
        Console.WriteLine($"方法{methodName}执行了行号:{lineNumber}");
    }
}

方案2:CLR Profiling API(无侵入高级方案)

如果需要完全无侵入的追踪,可以编写自定义CLR探查器,利用CLR Profiling API拦截方法执行并记录每一行的执行情况。不过这个方案实现复杂度较高,需要深入了解CLR的底层机制,适合需要全局监控的场景。


有没有内置的追踪类?

.NET Framework/.NET Core并没有提供直接一键获取执行行数的内置类,但上述提到的System.Diagnostics.SymbolStore、DiagnosticSource以及Roslyn都是官方提供的基础API,可以组合起来实现你的需求。如果愿意使用第三方工具,像PostSharp这类AOP框架可以轻松实现方法级的行追踪,但这属于第三方依赖。

内容的提问来源于stack exchange,提问作者Hewitt V S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:42:08