นี่คือตัวอย่างของสิ่งที่ฉันต้องการทำ:
MessageBox.Show("Error line number " + CurrentLineNumber);
ในโค้ดด้านบนCurrentLineNumber
ควรเป็นหมายเลขบรรทัดในซอร์สโค้ดของโค้ดส่วนนี้
ฉันจะทำเช่นนั้นได้อย่างไร?
นี่คือตัวอย่างของสิ่งที่ฉันต้องการทำ:
MessageBox.Show("Error line number " + CurrentLineNumber);
ในโค้ดด้านบนCurrentLineNumber
ควรเป็นหมายเลขบรรทัดในซอร์สโค้ดของโค้ดส่วนนี้
ฉันจะทำเช่นนั้นได้อย่างไร?
คำตอบ:
ใน. 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 + ")");
}
สิ่งนี้จะแสดงตัวอย่างเช่น:
Boo ที่บรรทัด 39 (SomeMethodSomewhere)
นอกจากนี้ยัง[CallerFilePath]
บอกเส้นทางของไฟล์โค้ดต้นฉบับด้วย
ใช้เมธอดStackFrame.GetFileLineNumberตัวอย่างเช่น:
private static void ReportError(string message)
{
StackFrame callStack = new StackFrame(1, true);
MessageBox.Show("Error: " + message + ", File: " + callStack.GetFileName()
+ ", Line: " + callStack.GetFileLineNumber());
}
ดูรายการ Blog ของ Scott Hanselmanสำหรับข้อมูลเพิ่มเติม
[แก้ไข: เพิ่มสิ่งต่อไปนี้]
สำหรับผู้ที่ใช้. Net 4.5 หรือใหม่กว่าให้พิจารณาแอ็ตทริบิวต์CallerFilePath , CallerMethodNameและCallerLineNumberในเนมสเปซ System.Runtime.CompilerServices ตัวอย่างเช่น:
public void TraceMessage(string message,
[CallerMemberName] string callingMethod = "",
[CallerFilePath] string callingFilePath = "",
[CallerLineNumber] int callingFileLineNumber = 0)
{
// Write out message
}
อาร์กิวเมนต์ต้องเป็นstring
สำหรับCallerMemberName
และCallerFilePath
และint
สำหรับCallerLineNumber
และต้องมีค่าเริ่มต้น การระบุแอ็ตทริบิวต์เหล่านี้บนพารามิเตอร์เมธอดจะสั่งให้คอมไพลเลอร์แทรกค่าที่เหมาะสมในโค้ดการเรียกในเวลาคอมไพล์ซึ่งหมายความว่ามันทำงานผ่านการทำให้สับสน ดูข้อมูลผู้โทรสำหรับข้อมูลเพิ่มเติม
StackFrame
ตัวอย่างในMonoอย่าลืมใช้--debug
ในเวลาคอมไพล์และรันไทม์
StackFrame
ไม่มีใน. NET Core ใช้คำตอบของ Marc Gravell
= string.Empty
ข้อผิดพลาด"ค่าพารามิเตอร์เริ่มต้นสำหรับ 'CallingFilePath' ต้องเป็นค่าคงที่เวลาคอมไพล์" !
""
) แทนstring.Empty
.
ฉันชอบหนึ่งสมุทรดังนั้น:
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!");
}
เอาท์พุท:
การทดสอบเป็นโมฆะ () (FILENAME.cs: 104)
ดูนี่!
เปลี่ยนรูปแบบ Console.WriteLine ตามที่คุณต้องการ!
System.Diagnostics.Debug.WriteLine(String.Format("{0}({1}): {2}: {3}", fileName, lineNumber, methodName, message));
คุณสามารถคลิกบรรทัดในหน้าต่างเอาต์พุตและไปที่บรรทัดนั้นในแหล่งที่มา
หากอยู่ในบล็อก 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 คุณสามารถรับหมายเลขบรรทัดได้โดยการสร้างฟังก์ชัน:
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