如何获取当前行号?

时间:2012-09-23 22:23:04

标签: c# wpf c#-4.0 line-numbers

以下是我想要做的一个例子:

 MessageBox.Show("Error line number "+CurrentLineNumber);

当前行号将是此段代码的源代码中的行号。

我该怎么做?

8 个答案:

答案 0 :(得分:147)

在.NET 4.5 / C#5中,您可以通过编写使用新调用方属性的实用程序方法让编译器为您完成此工作:

static void SomeMethodSomewhere()
{
    ShowMessage("Boo");
}
...
static void ShowMessage(string message,
    [CallerLineNumber] int lineNumber = 0,
    [CallerMemberName] string caller = null)
{
     MessageBox.Show(message + " at line " + lineNumber + " (" + caller + ")");
}

这将显示,例如:

  

第39行的Boo(SomeMethodSomewhere)

还有[CallerFilePath]告诉你原始代码文件的路径。

答案 1 :(得分:62)

使用StackFrame.GetFileLineNumber方法,例如:

private static void ReportError(string message)
{
     StackFrame callStack = new StackFrame(1, true);
     MessageBox.Show("Error: " + message + ", File: " + callStack.GetFileName() 
          + ", Line: " + callStack.GetFileLineNumber());
}

有关详细信息,请参阅Scott Hanselman's Blog entry

[编辑:添加以下内容]

对于使用.Net 4.5或更高版本的用户,请考虑System.Runtime.CompilerServices命名空间中的CallerFilePathCallerMethodNameCallerLineNumber属性。例如:

public void TraceMessage(string message,
        [CallerMemberName] string callingMethod = "",
        [CallerFilePath] string callingFilePath = "",
        [CallerLineNumber] int callingFileLineNumber = 0)
{
    // Write out message
}

stringCallerMemberName以及CallerFilePath的{​​{1}}参数必须为int且必须具有默认值。在方法参数上指定这些属性指示编译器在编译时在调用代码中插入适当的值,这意味着它通过模糊处理来工作。有关详细信息,请参阅Caller Information

答案 2 :(得分:17)

我更喜欢一个衬垫:

int lineNumber = (new System.Diagnostics.StackFrame(0, true)).GetFileLineNumber();

答案 3 :(得分:4)

对于那些需要.NET 4.0+方法解决方案的人:

using System;
using System.IO;
using System.Diagnostics;

public static void Log(string message) {
   StackFrame stackFrame = new System.Diagnostics.StackTrace(1).GetFrame(1);
   string fileName = stackFrame.GetFileName();
   string methodName = stackFrame.GetMethod().ToString();
   int lineNumber = stackFrame.GetFileLineNumber();

   Console.WriteLine("{0}({1}:{2})\n{3}", methodName, Path.GetFileName(fileName), lineNumber, message);
}

如何致电:

void Test() {
   Log("Look here!");
}

输出:

  

Void Test()(FILENAME.cs:104)

     

看这里!

按照您的喜好更改Console.WriteLine格式!

答案 4 :(得分:3)

如果它在try catch块中使用它。

try
{
    //Do something
}
catch (Exception ex)
{
    System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
    Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
}

答案 5 :(得分:1)

在.NET 4.5中,您可以通过创建函数来获取行号:

static int LineNumber([System.Runtime.CompilerServices.CallerLineNumber] int lineNumber = 0)
{
    return lineNumber; 
}

然后每次拨打LineNumber()时,您都会拥有当前行。这比使用StackTrace的任何解决方案都有优势,它应该在调试和发布中都能正常工作。

因此,根据所需要的原始要求,它将成为:

MessageBox.Show("Error enter code here line number " + LineNumber());

这是建立在Marc Gravell的优秀答案之上的。

答案 6 :(得分:0)

您只询问行号并且项目类型为空,然后需要使用类似的内容

internal class Utils
{
   public static int Line([CallerLineNumber] int? lineNumber =null)=>lineNumber;
}

在您的代码中,如果您想获取行号,则只需致电

var line=Utils.Line();

如果您正在记录日志,并且想要在说日志记录中记录行号,而不是调用这种方法

public void MyMethod(int someValue)
{
    switch(someValue)
    { 
        case 1:
            if(abc<xyz)
            {
             logger.LogInformation("case value {someValue} this line {line} was true", someValue ,Utils.Line()-2);
            }
            break;

        case 2:
           logger.LogInformation("case value {someValue} this {line} was executed",someValue,Utils.Line());
           break;
        caste 3:
           logger.LogInformation("case value {someValue} this {line} was executed",someValue,Utils.Line());
           break;
    }
}

您可以使用任何其他[CallerXXX]方法来扩展此模式,并且不要在任何地方使用它们,不仅在方法参数中使用。

在Nuget软件包Walter中,我使用了一个名为ExceptionObject的超酷类

如果导入NuGet包,则可以在Exception类上具有一些不错的扩展方法,并且可以访问显示调用链的CallStack,其中包括方法参数和所有被调用方法的参数值。

这就像一堆异常,只有值显示了如何获得值。

public void MyMethod()
{
    try
    {
    
      //get me all methods, signatures, parameters line numbers file names etc used as well as assembly info of all assemblies used for documentation of how the code got here
      var stack= new CallStack();
      foreach( var frame in StackedFrames)
      {
         logger.LogDebug(frame.ToString());
      }
    }
    catch(SqlException e)
    {
       var ex = new ExceptionObject(e);
       logger.LogException(e,"{this} exception due to {message} {server} {procedure} TSQL-line:{sqlline}\n{TSQL}"
                            ,e.GetType().Name
                            ,e.Message
                            ,ex.SqlServer
                            ,ex.SqlProcedureName
                            ,ex.SqlLineNumber
                            ,ex.Tsql
                            ,ex.CallStack); 
    }
    catch(Exception e)
    {
       var ex = new ExceptionObject(e);
       logger.LogException(e,"{this} exception due to {message} signature: signature}\nCallStack:", e.GetType().Name,e.Message,ex.Signature,ex.CallStack); 
    }
}

答案 7 :(得分:-7)

这对我有用:

try
{
 //your code;
}
catch(Exception ex)
{
  MessageBox.Show(ex.StackTrace + " ---This is your line number, bro' :)", ex.Message);
}