用于记录目的
__LINE__ __FILE__
我是C/C++的朋友.在Java中获取该信息,我不得不抛出异常并抓住它.为什么在现代编程语言中忽略了这些旧的备用语言?他们的简约有些神奇.
调用者信息已添加到.NET 4.5中.这将被编译,这是一个必须手动检查堆栈跟踪的重大改进.
public void Log(string message, [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0) { // Do logging }
只需以这种方式调用它,编译器就会为您填写文件名和行号:
logger.Log("Hello!");
这很丑陋,但您可以使用StackTrace和StackFrame类在C#中执行以下操作:
StackTrace st = new StackTrace(new StackFrame(true)); Console.WriteLine(" Stack trace for current level: {0}", st.ToString()); StackFrame sf = st.GetFrame(0); Console.WriteLine(" File: {0}", sf.GetFileName()); Console.WriteLine(" Method: {0}", sf.GetMethod().Name); Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber()); Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());
当然,这带来了一些开销.
与此最接近的是,您可以创建一个StackTrace
对象并在堆栈顶部找出方法的名称,这样您就可以接近__FUNCTION__
宏的功能.
StackTrace stackTrace = new StackTrace(); StackFrame[] stackFrames = stackTrace.GetFrames(); foreach (StackFrame stackFrame in stackFrames) Console.WriteLine(stackFrame.GetMethod().Name);
为了降低手动输入的成本以及运行时代码,您可以编写一个辅助方法:
[Conditional("Debug")] public void LogMethodName() { Trace.WriteLine("Entering:" + new StackTrace().GetFrame(1).GetMethod().Name); }
注意我们如何获得第1帧,因为第0帧LogMethodName
本身就是.通过将其标记为条件("调试"),我们确保从发布版本中删除代码,这是避免可能不需要的运行时成本的一种方法.
随着来电信息(在.NET 4.5中引入),您可以创建相当于__LINE__
与__FILE__
在C#中:
static int __LINE__([System.Runtime.CompilerServices.CallerLineNumber] int lineNumber = 0) { return lineNumber; } static string __FILE__([System.Runtime.CompilerServices.CallerFilePath] string fileName = "") { return fileName; }
唯一要记住的是,这些是函数,而不是编译器指令。
因此,例如:
MessageBox.Show("Line " + __LINE__() + " in " + __FILE__());
如果您要在实践中使用此名称,那么我建议使用其他名称。我使用C / C ++名称只是为了更清楚它们返回的内容,诸如CurrentLineNumber()
和CurrentFileName()
可能是更好的名称。
与任何使用的解决方案相比,使用呼叫者信息的优势StackTrace
在于,行和文件信息可用于调试和发布。