前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈StackTrace类

浅谈StackTrace类

作者头像
小蜜蜂
发布2019-07-15 16:19:26
1.5K0
发布2019-07-15 16:19:26
举报
文章被收录于专栏:明丰随笔

在写通用组件的时候,我们需要关心程序运行的堆栈信息。堆栈信息是什么?

堆栈是一种执行“后进先出”算法的数据结构。程序的函数调用是用堆栈实现的。

在程序中,每次调用一个函数,就会生成一个堆栈帧,并push进入堆栈中。每一次结束一个函数调用,就会从堆栈中pop一个堆栈帧。

在.Net Framework中,定义了StackTrace类,它可以获取当前堆栈的每一帧的信息。

它的构造函数:

代码语言:javascript
复制
//默认不获取文件信息
StackTrace();
//是否获取文件信息,包括文件名,行号等
StackTrace(bool fNeedFileInfo);
//可以指定跳过帧的数量
StackTrace(int skipFrames);
StackTrace(int skipFrames, bool fNeedFileInfo);
//根据提供的Exception对象,生成堆栈信息
StackTrace(Exception e);
StackTrace(Exception e, bool fNeedFileInfo);
StackTrace(Exception e, int skipFrames);
StackTrace(Exception e, int skipFrames, bool fNeedFileInfo);

它的属性:

代码语言:javascript
复制
//返回堆栈信息的帧的数量
int FrameCount;

它的方法:

代码语言:javascript
复制
//返回堆栈信息的所有帧
StackFrame[] GetFrames();
//根据帧的索引,返回帧
StackFrame GetFrame(int index);

StackFrame类提供的方法:

代码语言:javascript
复制
int GetFileLineNumber();
int GetFileColumnNumber();
string GetFileName();
MethodBase GetMethod();

做一个简单的练习:

代码语言:javascript
复制
static void Main(string[] args)
{
  StackTraceSample stackTraceSample = new StackTraceSample();
  try
  {
    stackTraceSample.MyPublicMethod();
  }
  catch (Exception e)
  {
    // Create a StackTrace that captures
    // filename, line number, and column
    // information for the current thread.
    StackTrace st = new StackTrace(e, true);
    string stackIndent = "";
    for (int i = 0; i < st.FrameCount; i++)
    {
      // Note that high up the call stack, there is only
      // one stack frame.
      StackFrame sf = st.GetFrame(i);
      Console.WriteLine();
      Console.WriteLine(stackIndent + " Method: {0}",
        sf.GetMethod());
      Console.WriteLine(stackIndent + " File: {0}",
        sf.GetFileName());
      Console.WriteLine(stackIndent + " Line Number: {0}"
        , sf.GetFileLineNumber());
      stackIndent += "  ";
    }
  }
  Console.ReadKey();
}

public class StackTraceSample
{
  public void MyPublicMethod()
  {
    MyProtectedMethod();
  }
  protected void MyProtectedMethod()
  {
    MyInternalClass mic = new MyInternalClass();
    mic.ThrowsException();
  }
  class MyInternalClass
  {
    public void ThrowsException()
    {
      try
      {
        throw new Exception("A problem was encountered.");
      }
      catch (Exception)
      {
        // Create a StackTrace that captures filename,
        // line number and column information.
        StackTrace st = new StackTrace(true);
        string stackIndent = "";
        for (int i = 0; i < st.FrameCount; i++)
        {
          // Note that at this level, there are four
          // stack frames, one for each method invocation.
          StackFrame sf = st.GetFrame(i);
          Console.WriteLine();
          Console.WriteLine(stackIndent + " Method: {0}",
            sf.GetMethod());
          Console.WriteLine(stackIndent + " File: {0}",
            sf.GetFileName());
          Console.WriteLine(stackIndent + " Line Number: {0}"
            ,sf.GetFileLineNumber());
          stackIndent += "  ";
        }
        throw;
      }
    }
  }
}

运行的结果:

我们这里的堆栈信息并不能获取每一个函数在调用的时候,传递的参数值,对于有这种需求的程序员,可以考虑使用AOP编程的方式编写一个MethodContextLogger组件,这个组件可以获取方法的出入的参数值,并记录下来。关于如何实现AOP编程,可以参考我之前的文章。

-纸上得来终觉浅,绝知此事要躬行-

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 明丰随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档