C# 如何获取当前的行号?

C# 如何获取当前的行号?,c#,wpf,c#-4.0,line-numbers,C#,Wpf,C# 4.0,Line Numbers,下面是我想做的一个例子: MessageBox.Show(“错误行号”+CurrentLineNumber); 在上面的代码中,CurrentLineNumber应该是这段代码源代码中的行号 我如何才能做到这一点?使用该方法,例如: private static void ReportError(string message) { StackFrame callStack = new StackFrame(1, true); MessageBox.Show("Error:

下面是我想做的一个例子:

MessageBox.Show(“错误行号”+CurrentLineNumber);
在上面的代码中,
CurrentLineNumber
应该是这段代码源代码中的行号

我如何才能做到这一点?

使用该方法,例如:

private static void ReportError(string message)
{
     StackFrame callStack = new StackFrame(1, true);
     MessageBox.Show("Error: " + message + ", File: " + callStack.GetFileName() 
          + ", Line: " + callStack.GetFileLineNumber());
}
public void TraceMessage(string message,
        [CallerMemberName] string callingMethod = "",
        [CallerFilePath] string callingFilePath = "",
        [CallerLineNumber] int callingFileLineNumber = 0)
{
    // Write out message
}
有关更多信息,请参阅

[编辑:添加以下内容]

<>对于使用.NET 4.5或更高版本的用户,请考虑Stase.RunTime.CuffiServices命名空间中的属性和属性。例如:

private static void ReportError(string message)
{
     StackFrame callStack = new StackFrame(1, true);
     MessageBox.Show("Error: " + message + ", File: " + callStack.GetFileName() 
          + ", Line: " + callStack.GetFileLineNumber());
}
public void TraceMessage(string message,
        [CallerMemberName] string callingMethod = "",
        [CallerFilePath] string callingFilePath = "",
        [CallerLineNumber] int callingFileLineNumber = 0)
{
    // Write out message
}

对于
CallerMemberName
CallerFilePath
而言,参数必须是
string
,对于
CallerLineNumber
而言,参数必须是
int
,并且必须具有默认值。在方法参数上指定这些属性将指示编译器在编译时在调用代码中插入适当的值,这意味着它可以通过模糊处理工作。有关更多信息,请参阅。

如果它位于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());
}
在.NET 4.5/C#5中,您可以通过编写使用新调用方属性的实用程序方法,让编译器为您完成这项工作:

using System.Runtime.CompilerServices;

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 + ")");
}
这将显示,例如:

private static void ReportError(string message)
{
     StackFrame callStack = new StackFrame(1, true);
     MessageBox.Show("Error: " + message + ", File: " + callStack.GetFileName() 
          + ", Line: " + callStack.GetFileLineNumber());
}
public void TraceMessage(string message,
        [CallerMemberName] string callingMethod = "",
        [CallerFilePath] string callingFilePath = "",
        [CallerLineNumber] int callingFileLineNumber = 0)
{
    // Write out message
}
第39行的Boo(某处)


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

我更喜欢一行,这样:

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

对于需要.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格式,如您所愿

在.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的优秀答案。

您只询问了行号,对于可为空的项目类型,您需要使用类似这样的

internal class Utils
{
   public static int Line([CallerLineNumber] int? lineNumber =null)=>lineNumber;
}
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;
    }
}
在你的代码中,如果你想得到一个电话号码,你只需要打电话

var line=Utils.Line();
如果您正在进行日志记录,并且希望在say logging中记录行号,那么可以像这样调用该方法

internal class Utils
{
   public static int Line([CallerLineNumber] int? lineNumber =null)=>lineNumber;
}
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;
    }
}

您不能可靠地做到这一点,因为JIT编译器可以进行优化(例如内联代码),这意味着您的行号将是错误的。因为如果您愿意,可以关闭优化,因此您可以可靠地做到这一点。@MonsterMMORPG的可能重复项无论是否存在错误都有效。StackFrame类只是查看调用当前正在执行的方法。StackFrame构造函数的第一个参数是调用深度(1),第二个参数表示需要文件信息。如果您在Mono上编译
StackFrame
示例,请确保在编译时和运行时使用
--debug
StackFrame
在.NET Core中不可用。使用Marc Gravell的答案。使用默认值
=string.Empty
会抛出错误“callingFilePath”的默认参数值必须是编译时常量”@stomy我将examp[le改为使用双引号(
“”
)而不是
string.Empty
。非常感谢你的回答。这也可以学习对象名吗?哦,我与其他东西混淆了。我想知道的是asp.net 4.5网站。全局错误捕获器。捕获由错误引起的对象名?@MonsterMMORPG不;只是我提到的3个above@MarcGravell这是否需要运行时环境is也应该是4.5或者它是一个编译器功能?不会在所有情况下都工作..它总是需要.pdb文件,我们通常不会生成/复制到生产服务器。请尝试使用C#5.0 Caller*属性。如果改为使用此属性:
System.Diagnostics.Debug.WriteLine(String.Format({0}({1}):{2}:{3})、文件名、行号、方法名、消息));
然后,您可以单击输出窗口中的行,并被带到源代码中的那一行。它需要.pdb文件..我们通常不会生成/复制到生产服务器。这不会返回正确的行号。出于某种原因,我必须减去191才能正确。有趣。对我来说,在这里工作很好。是否打开了链接号在IDE中打开?如果从文件中的不同位置调用此函数,是否仍需要减去191?这可能是编译器错误(不太可能,但可能),也可能是页面上的折叠块(虽然这不应妨碍行号的正确性,但如果您是在计数而不是查找行号,则可能会解释差异).如果你能离线联系我,那么我很想知道到底是怎么回事。没有折叠块,行号是打开的,无论从哪里调用,都必须减去191。我知道…奇怪。