Mevcut satır numarasını nasıl alırım?


118

İşte yapmak istediğim şeye bir örnek:

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

Yukarıdaki CurrentLineNumberkodda, bu kod parçasının kaynak kodundaki satır numarası olmalıdır.

Bunu nasıl yapabilirim?


Sen olamaz güvenilir JIT derleyicisi optimizasyonları (örn inlining kodu) yapabilir gibi satır numaraları yanlış olacaktır, yani, bunu.
adrianbanks

1
Eğer isterseniz optimizasyon kapatabilirsiniz olduğundan, olabilir güvenilir bunu.
jwg

Yanıtlar:


175

.NET 4.5 / C # 5'te, yeni arayan özniteliklerini kullanan bir yardımcı program yöntemi yazarak derleyicinin bu işi sizin için yapmasını sağlayabilirsiniz:

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

Bu, örneğin şunu gösterecektir:

39. satırda Boo (SomeMethodSomewhere)

Ayrıca [CallerFilePath]size orijinal kod dosyasının yolunu söyleyenler de var .


cevap için çok teşekkürler. nesne adını da öğrenmek mümkün müdür? oh başka bir şeyle karıştırdım merak ettiğim şey asp.net 4.5 web sitesi. genel hata yakalayıcı. nesne adına neden olan hatayı yakalamak?
MonsterMMORPG

@MonsterMMORPG hayır; sadece yukarıda bahsettiğim 3
Marc Gravell

1
@MarcGravell bunun için Çalışma zamanı ortamının da 4.5 olması gerekir mi VEYA bu bir derleyici özelliği mi?
kuldeep

5
C # çok iyi tasarlanmış. Beni şaşırtmaktan asla vazgeçmiyor. Teşekkürler Marc!
nmit026

74

StackFrame.GetFileLineNumber yöntemini kullanın, örneğin:

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

Daha fazla bilgi için Scott Hanselman'ın Blog girişine bakın.

[Düzenle: Aşağıdakileri ekledi]

.Net 4.5 veya üzerini kullananlar için, System.Runtime.CompilerServices ad alanındaki CallerFilePath , CallerMethodName ve CallerLineNumber özniteliklerini göz önünde bulundurun . Örneğin:

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

Argümanlar stringfor CallerMemberNameve CallerFilePathve intfor CallerLineNumberolmalıdır ve varsayılan bir değere sahip olmalıdır. Yöntem parametrelerinde bu özniteliklerin belirtilmesi, derleyiciye çağıran koda uygun değeri derleme zamanında ekleme talimatı verir, yani gizleme yoluyla çalışır. Daha fazla bilgi için Arayan Bilgileri'ne bakın .


@MonsterMMORPG Bu, bir hata olup olmadığına bakılmaksızın çalışır. StackFrame sınıfı, sadece çalıştırılan mevcut yöntemi çağıran yönteme bakmaktadır. StackFrame yapıcısının ilk argümanı çağrı derinliğidir (1) ve ikinci argüman dosya bilgilerinin gerekli olduğunu belirtir.
akton

3
Eğer derleme yapıyorsanız StackFrameörneğe Mono , emin için olmak kullanmak--debug derleme zamanında ve çalışma zamanında
bernard paulus

StackFrame.NET Core'da mevcut değildir. Marc Gravell'in cevabını kullanın.
Jesse Chisholm

Varsayılan değeri kullanmak, "'DosyaYolunu çağırmak için varsayılan parametre değeri bir derleme zamanı sabiti olmalıdır"= string.Empty hatası verir !
stomy

1
@stomy Örneği [le ""yerine çift ​​tırnak ( ) kullanacak şekilde değiştirdim string.Empty.
akton

22

Ben bir gömlek tercih ederim, bu yüzden:

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

8
.pdb dosyasına ihtiyacı var .. ki bunu genellikle oluşturmuyoruz / üretim sunucusuna kopyalamıyoruz.
Deepak Sharma

4

.NET 4.0+ yöntem çözümüne ihtiyaç duyanlar için:

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

Nasıl aranır:

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

Çıktı:

Geçersizlik Testi () (FILENAME.cs: 104)

Buraya bak!

Console.WriteLine formatını istediğiniz gibi değiştirin!


3
her durumda çalışmayacaktır .. her zaman .pdb dosyasına ihtiyacı vardır, ki biz genellikle bunu üretmiyoruz / üretim sunucusuna kopyalamıyoruz. C # 5.0 Caller * özelliği ile deneyin.
Deepak Sharma

2
Bunun yerine şunu kullanırsanız: System.Diagnostics.Debug.WriteLine(String.Format("{0}({1}): {2}: {3}", fileName, lineNumber, methodName, message));çıktı penceresindeki satırı tıklayabilir ve kaynakta o satıra götürülebilirsiniz.
Jesse Chisholm

3

Bir deneme yakalama bloğu ise bunu kullanın.

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'te, işlevi oluşturarak satır numarasını alabilirsiniz:

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

Daha sonra her aradığınızda LineNumber()mevcut hattınız olacak. Bu, hem hata ayıklamada hem de yayınlamada çalışması gereken StackTrace'i kullanan herhangi bir çözüme göre avantajlıdır.

Böylece, gerekli olanın orijinal talebini alırsanız, şu olur:

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

Bu, Marc Gravell'in mükemmel cevabına dayanıyor.


Bu, doğru satır numarasını döndürmez. Bir sebepten dolayı doğru yapmak için 191 çıkarmam gerekiyor.
Daniel

İlginç. Burada benim için iyi çalışıyor. IDE'de açık bağlantı numaralarınız var mı? Bu işlevi dosyanın farklı yerlerinden çağırırsanız, yine de 191'i çıkarmak zorunda mısınız? Bu, ya bir derleyici hatası (olası değildir, ancak olası) ya da sayfanızdaki daraltılmış bir blok olacaktır (bu, satır numaralarının doğru olmasını engellememelidir, ancak satır numarasına bakmak yerine sayıyorsanız farkı açıklayabilir). Benimle çevrimdışı iletişim kurabilirseniz, konuya girmek isterim.
Brian Cryer

Daraltılmış blok yok, satır numaraları açık, nereden çağrıldığına bakılmaksızın yine de 191 çıkarmak zorunda. Biliyorum ... tuhaf.
Daniel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.