현재 라인 번호는 어떻게 얻습니까?


117

다음은 내가 원하는 작업의 예입니다.

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

위의 코드에서는이 코드 CurrentLineNumber의 소스 코드에있는 줄 번호 여야합니다.

어떻게 할 수 있습니까?


JIT 컴파일러가 최적화 (예 : 인라인 코드)를 수행 할 수 있으므로이 작업을 안정적으로 수행 할 수 없습니다 . 즉, 줄 번호가 잘못 될 것입니다.
adrianbanks

1
원하는 경우 최적화를 끌 수 있으므로 안정적으로 수행 할 수 있습니다 .
jwg

답변:


175

.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]원본 코드 파일의 경로를 알려주는 것도 있습니다.


답변 해 주셔서 감사합니다. 객체 이름도 배울 수 있습니까? 오, 다른 것과 혼동했습니다. 내가 궁금한 것은 asp.net 4.5 웹 사이트입니다. 글로벌 오류 포수. 오류로 인해 개체 이름을 잡으셨습니까?
MonsterMMORPG

@MonsterMMORPG 아니에요; 위에서 언급 한 3 개만
Marc Gravell

1
@MarcGravell은 런타임 환경이 4.5 여야하거나 컴파일러 기능이어야합니까?
kuldeep

5
C #은 매우 잘 설계되었습니다. 그것은 나를 놀라게하는 것을 멈추지 않습니다. 감사합니다 마크!
nmit026

74

예를 들어 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의 블로그 항목 을 참조하십시오.

[편집 : 다음 추가]

.Net 4.5 이상을 사용 하는 경우 System.Runtime.CompilerServices 네임 스페이스 의 CallerFilePath , CallerMethodNameCallerLineNumber 속성을 고려하십시오 . 예를 들면 :

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

인수는 stringfor CallerMemberNameCallerFilePathintfor CallerLineNumber여야하며 기본값이 있어야합니다. 메서드 매개 변수에 이러한 특성을 지정하면 컴파일 타임에 적절한 값을 호출 코드에 삽입하도록 컴파일러에 지시합니다. 즉, 난독 화를 통해 작동합니다. 자세한 내용은 발신자 정보 를 참조하십시오.


@MonsterMMORPG 이것은 오류가 있는지 여부에 관계없이 작동합니다. StackFrame 클래스는 실행중인 현재를 호출하는 메서드 만보고 있습니다. StackFrame 생성자의 첫 번째 인수는 호출 깊이 (1)이고 두 번째 인수는 파일 정보가 필요함을 나타냅니다.
akton

3
Mono 에서 StackFrame예제를 컴파일하는 경우 컴파일 시간과 런타임 에 사용 하십시오--debug
bernard paulus

StackFrame.NET Core에서는 사용할 수 없습니다. Marc Gravell의 대답을 사용하십시오.
제시 치솜

기본값을 사용하면 " 'callingFilePath'에 대한 기본 매개 변수 값은 컴파일 시간 상수 여야합니다."= string.Empty 오류가 발생 합니다 !
stomy

1
@stomy ""대신 큰 따옴표 ( ) 를 사용하도록 시험을 변경했습니다 string.Empty.
akton

21

나는 하나의 라이너를 선호합니다.

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

8
일반적으로 프로덕션 서버에 생성 / 복사하지 않는 .pdb 파일 ..이 필요합니다.
Deepak Sharma 2015 년

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 형식을 변경하십시오!


3
모든 경우에 작동하지 않습니다 .. 항상 .pdb 파일이 필요하며 일반적으로 프로덕션 서버에 생성 / 복사하지 않습니다. C # 5.0 Caller * 속성으로 시도하십시오.
Deepak Sharma 15.

2
대신 이것을 사용하는 경우 : System.Diagnostics.Debug.WriteLine(String.Format("{0}({1}): {2}: {3}", fileName, lineNumber, methodName, message));출력 창에서 라인을 클릭하고 소스의 해당 라인으로 이동할 수 있습니다.
제시 치솜

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

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의 탁월한 답변을 기반으로합니다.


이것은 올바른 줄 번호를 반환하지 않습니다. 어떤 이유로 든 제대로하려면 191을 빼야합니다.
Daniel

흥미 롭군. 여기에서 잘 작동합니다. IDE에서 링크 번호가 켜져 있습니까? 파일의 다른 위치에서이 함수를 호출하는 경우 여전히 191을 빼야합니까? 이것은 컴파일러 버그 (가능성이 낮지 만 가능함)이거나 페이지의 축소 된 블록 일 것입니다 (줄 번호가 올바른지 확인하는 것을 방해해서는 안되지만 줄 번호를 찾는 대신 계산하는 경우 차이를 설명 할 수 있음). 오프라인으로 저에게 연락 할 수 있다면 그 문제를 해결하고 싶습니다.
Brian Cryer

접힌 블록이없고 라인 번호가 켜져 있으며 호출 된 위치에 관계없이 191을 빼야합니다. 알아 ... 이상해.
Daniel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.