c#关于Diagnostics的StackFrame类的理解
在做项目的过程中无意中看到了在使用日志的过程中用到了StackFrame这个类,StackFrame frame = new StackFrame(1);在这行代码中有一个1,这里有一个1始终不理解,查看fcl的官方解释:
//
// 摘要:
// 初始化与当前堆栈帧之上的帧对应的 System.Diagnostics.StackFrame 类的新实例。
//
// 参数:
// skipFrames:
// 堆栈上要跳过的帧数。
云里雾里?关键是理解什么是堆栈帧?好了堆栈帧的解释:--“堆栈帧是在堆栈中为当前正在运行的函数分配的区域(或空间)。传入的参数、返回地址(当这个函数结束后必须跳转到该返回地址。译注:即主调函数的断点处)以及函数所用的内部存储单元(即函数存储在堆栈上的局部变量)都在堆栈帧中。
还是不太懂。。。。看一个图也许会清楚一些:
对应的代码如下:
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