How do I get the current line number?

Here is an example of what I want to do:

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

In the code above the CurrentLineNumber, should be the line number in the source code of this piece of code.

How can I do that?


Solution 1:

In .NET 4.5 / C# 5, you can get the compiler to do this work for you, by writing a utility method that uses the new caller attributes:

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 + ")");
}

This will display, for example:

Boo at line 39 (SomeMethodSomewhere)

There's also [CallerFilePath] which tells you the path of the original code file.

Solution 2:

Use the StackFrame.GetFileLineNumber method, for example:

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

See Scott Hanselman's Blog entry for more information.

[Edit: Added the following]

For those using .Net 4.5 or later, consider the CallerFilePath, CallerMethodName and CallerLineNumber attributes in the System.Runtime.CompilerServices namespace. For example:

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

The arguments must be string for CallerMemberName and CallerFilePath and an int for CallerLineNumber and must have a default value. Specifying these attributes on method parameters instructs the compiler to insert the appropriate value in the calling code at compile time, meaning it works through obfuscation. See Caller Information for more information.

Solution 3:

I prefer one liners so:

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

Solution 4:

For those who need a .NET 4.0+ method solution:

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);
}

How to call:

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

Output:

Void Test()(FILENAME.cs:104)

Look here!

Change the Console.WriteLine format how you like!