Làm cách nào để lấy số dòng hiện tại?


117

Đây là một ví dụ về những gì tôi muốn làm:

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

Trong đoạn mã trên CurrentLineNumber, phải là số dòng trong mã nguồn của đoạn mã này.

Làm thế nào tôi có thể làm điều đó?


Bạn không thể làm điều này một cách đáng tin cậy , vì trình biên dịch JIT có thể tối ưu hóa (ví dụ: mã nội tuyến), có nghĩa là số dòng của bạn sẽ bị sai.
adrianbanks

1
Vì bạn có thể tắt tính năng tối ưu hóa nếu muốn nên bạn hoàn toàn có thể thực hiện việc này.
jwg

Câu trả lời:


175

Trong .NET 4.5 / C # 5, bạn có thể yêu cầu trình biên dịch thực hiện công việc này cho bạn, bằng cách viết một phương thức tiện ích sử dụng các thuộc tính người gọi mới:

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

Điều này sẽ hiển thị, ví dụ:

Boo ở dòng 39 (SomeMethodSomewhere)

Ngoài ra còn [CallerFilePath]có nó cho bạn biết đường dẫn của tệp mã gốc.


Cảm ơn rất nhiều cho câu trả lời. là có thể tìm hiểu cả tên đối tượng? oh tôi nhầm lẫn với một cái gì đó khác. những gì tôi thắc mắc là trang web asp.net 4.5. trình bắt lỗi toàn cầu. bắt lỗi tên đối tượng gây ra?
MonsterMMORPG

@MonsterMMORPG nope; chỉ là 3 tôi đã đề cập ở trên
Marc Gravell

1
@MarcGravell điều này yêu cầu môi trường Thời gian chạy cũng phải là 4,5 HOẶC nó là một tính năng biên dịch?
kuldeep

5
C # được thiết kế rất tốt. Nó không bao giờ hết ngạc nhiên tôi. Cảm ơn Marc!
nmit026

74

Sử dụng phương thức StackFrame.GetFileLineNumber , ví dụ:

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

Xem mục Blog của Scott Hanselman để biết thêm thông tin.

[Chỉnh sửa: Đã thêm phần sau]

Đối với những người sử dụng .Net 4.5 trở lên, hãy xem xét các thuộc tính CallerFilePath , CallerMethodNameCallerLineNumber trong không gian tên System.Runtime.CompilerServices. Ví dụ:

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

Các đối số phải là stringfor CallerMemberNameCallerFilePathintfor CallerLineNumbervà phải có giá trị mặc định. Việc chỉ định các thuộc tính này trên các tham số phương thức hướng dẫn trình biên dịch chèn giá trị thích hợp vào mã đang gọi tại thời điểm biên dịch, nghĩa là nó hoạt động thông qua obfuscation. Xem Thông tin Người gọi để biết thêm thông tin.


@MonsterMMORPG Tính năng này hoạt động bất kể có lỗi hay không. Lớp StackFrame chỉ xem xét phương thức gọi hiện tại đang được thực thi. Đối số đầu tiên cho hàm tạo StackFrame là độ sâu lệnh gọi (1) và đối số thứ hai chỉ ra rằng thông tin tệp là cần thiết.
akton

3
Nếu bạn đang biên soạn các StackFrameví dụ trên Mono , hãy chắc chắn để sử dụng--debug tại thời gian biên dịch và tại thời gian chạy
bernard Paulus

StackFramekhông có sẵn trong .NET Core. Sử dụng câu trả lời của Marc Gravell.
Jesse Chisholm

Sử dụng giá trị mặc định = string.Emptyném ra lỗi "Giá trị tham số mặc định cho 'callFilePath' phải là hằng số thời gian biên dịch" !
stomy

1
@stomy Tôi đã thay đổi examp [le để sử dụng dấu ngoặc kép ( "") thay vì string.Empty.
akton

21

Tôi thích một lớp lót nên:

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

8
nó cần tệp .pdb .. mà chúng tôi thường không tạo / sao chép vào máy chủ sản xuất.
Deepak Sharma

4

Đối với những người cần giải pháp phương pháp .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);
}

Cách gọi:

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

Đầu ra:

Kiểm tra Void () (FILENAME.cs: 104)

Nhìn đây!

Thay đổi định dạng Console.WriteLine theo cách bạn muốn!


3
sẽ không hoạt động trong mọi trường hợp .. nó luôn cần tệp .pdb, mà chúng tôi thường không tạo / sao chép vào máy chủ sản xuất. thử với thuộc tính C # 5.0 Caller *.
Deepak Sharma

2
Thay vào đó, nếu bạn sử dụng điều này: System.Diagnostics.Debug.WriteLine(String.Format("{0}({1}): {2}: {3}", fileName, lineNumber, methodName, message));thì bạn có thể nhấp vào dòng trong cửa sổ đầu ra và được đưa đến dòng đó trong nguồn.
Jesse Chisholm

3

Nếu nó trong một khối try catch hãy sử dụng cái này.

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

1

Trong .NET 4.5, bạn có thể lấy số dòng bằng cách tạo hàm:

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

Sau đó, mỗi lần bạn gọi LineNumber()bạn sẽ có dòng hiện tại. Điều này có lợi thế hơn bất kỳ giải pháp nào sử dụng StackTrace là nó sẽ hoạt động trong cả gỡ lỗi và phát hành.

Vì vậy, lấy yêu cầu ban đầu của những gì được yêu cầu, nó sẽ trở thành:

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

Điều này được xây dựng dựa trên câu trả lời xuất sắc của Marc Gravell.


Điều này không trả về số dòng bên phải. Tôi phải trừ đi 191 vì một số lý do.
Daniel

Hấp dẫn. Hoạt động tốt ở đây đối với tôi. Bạn đã bật số liên kết trong IDE chưa? Nếu bạn gọi hàm này từ các vị trí khác nhau trong tệp, bạn vẫn phải trừ đi 191? Đây sẽ là một lỗi trình biên dịch (không chắc, nhưng có thể xảy ra) hoặc một khối được thu gọn trên trang của bạn (trong khi điều đó không ngăn số dòng chính xác, nó có thể giải thích sự khác biệt nếu bạn đang đếm thay vì tìm kiếm số dòng). Nếu bạn có thể liên hệ với tôi ngoại tuyến thì tôi muốn tìm hiểu sâu hơn về vấn đề này.
Brian Cryer

Không có khối được thu gọn, số dòng được bật, vẫn phải trừ 191 bất kể nó được gọi từ đâu. Tôi biết ... kỳ lạ.
Daniel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.