c#关于Diagnostics的StackFrame类的理解

在做项目的过程中无意中看到了在使用日志的过程中用到了StackFrame这个类,StackFrame frame = new StackFrame(1);在这行代码中有一个1,这里有一个1始终不理解,查看fcl的官方解释:

//
        // 摘要:
        //     初始化与当前堆栈帧之上的帧对应的 System.Diagnostics.StackFrame 类的新实例。
        //
        // 参数:
        //   skipFrames:
        //     堆栈上要跳过的帧数。

云里雾里?关键是理解什么是堆栈帧?好了堆栈帧的解释:--“堆栈帧是在堆栈中为当前正在运行的函数分配的区域(或空间)。传入的参数、返回地址(当这个函数结束后必须跳转到该返回地址。译注:即主调函数的断点处)以及函数所用的内部存储单元(即函数存储在堆栈上的局部变量)都在堆栈帧中。

还是不太懂。。。。看一个图也许会清楚一些:

c#关于Diagnostics的StackFrame类的理解

对应的代码如下:

class Program
    {
        static void MethodA(int par1,int par2) {
            MethodB(11,18);
        }


        static void MethodB(int par1,int par2) {
        }


        static void Main(string[] args)
        {
             MethodA(15,30);
            Console.ReadKey();
        }

    }

好了很简单,main()调用methodA(),methodA()调用methodB(),就是两层函数调用。接下来有一个关键点是栈是一个先进后出(FILO)的结构,在从图上很容易就明白了,堆栈帧的定义了,即main()方法在调用时需要在栈上保存的一些数据所对应的内存就是main的堆栈帧,同理methodA()方法对应的就是methodA的堆栈帧了。(如果还是不明白建议再看一遍图和文字)

好了理解了这个理论概念后,接下来用代码实践一下:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Diagnostics; //需要知道源码位置
6  
7 namespace ConsoleApplication1
8 {
9     class Program
10     {
11         static void   FirstLevel()
12         {
13               StackFrame   stackFrame = new StackFrame(1, true);
14               Console.WriteLine(stackFrame.GetFileName()); //获取包含所执行代码的文件名。
15               Console.WriteLine(stackFrame.GetFileLineNumber().ToString());   //也就是FirstLevel()被调用地方的行号
16               Console.WriteLine(stackFrame.GetFileColumnNumber().ToString());   //也就是FirstLevel()被调用地方的第一个字母“F”所处的列
17               Console.WriteLine(stackFrame.GetMethod().Module);   //stackFrame.GetMethod()获取在其中执行帧的方法。
18               Console.WriteLine(stackFrame.GetMethod().ReflectedType);
19               Console.WriteLine(stackFrame.GetMethod().ToString());
20         }
21  
22         static void   SecondLevel()
23         {
24               FirstLevel();
25         }
26  
27         static void   Main(string[] args)
28         {
29               SecondLevel();
30               Console.ReadKey();
31         }
32     }
33 }

输出如下:

C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs
24
13
ConsoleApplication1.exe
ConsoleApplication1.Program
Void SecondLevel()

关键是这个24的输出,他表示FirstLevel()被调用的行号,这样就清楚明白了StackFrame   stackFrame = new StackFrame(1, true);中1的意思了,就是指在堆栈帧中跳过的帧数,没错!!因为StackFrame   stackFrame = new StackFrame(1, true);是在FirstLevel()方法中定义的所以,跳过1帧就跟踪到了调用FirstLevel()的地方了,如果不出所料stackFrame = new StackFrame(2, true);原来输出24的地方应该输出29,(即SecondLevel();被调用的地方的行号)

参考博文https://www.cnblogs.com/chenjiawei-huster/p/3798161.html

https://blog.csdn.net/LUOCHENLONG/article/details/80420214