मुझे वर्तमान लाइन नंबर कैसे मिलेगा?


117

यहाँ एक उदाहरण है कि मैं क्या करना चाहता हूँ:

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

से ऊपर के CurrentLineNumberकोड में, इस कोड के स्रोत कोड में लाइन नंबर होना चाहिए।

मैं उसे कैसे कर सकता हूँ?


आप मज़बूती से ऐसा नहीं कर सकते , क्योंकि जेआईटी कंपाइलर ऑप्टिमाइज़ेशन (जैसे इनलाइन कोड) कर सकता है, जिसका अर्थ है कि आपके लाइन नंबर गलत होंगे।
एड्रियनबैंक्स

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 लाइन (SomeMethodSomewhere) पर

वहाँ भी है [CallerFilePath]जो आपको मूल कोड फ़ाइल का पथ बताता है।


उत्तर के लिए बहुत बहुत धन्यवाद। क्या यह भी संभव है कि वस्तु का नाम भी जानें? ओह मैं कुछ और के साथ भ्रमित क्या मुझे आश्चर्य है कि asp.net 4.5 वेबसाइट है। वैश्विक त्रुटि पकड़ने वाला। ऑब्जेक्ट नाम के कारण त्रुटि पकड़ ली?
मॉन्स्टरमोरपीजी

@MonsterMMORPG नोप; सिर्फ 3 मैं उपर्युक्त
मार्क Gravell

1
@MarcGravell के लिए यह आवश्यक है कि रन टाइम वातावरण भी 4.5 होना चाहिए या यह एक संकलक सुविधा है?
कुलदीप

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

स्कॉट हैनेलमैन की ब्लॉग प्रविष्टि देखें में अधिक जानकारी के लिए।

[संपादित करें: निम्नलिखित जोड़ा गया]

का उपयोग करने वालों के लिए .net 4.5 या बाद में, पर विचार करें , System.Runtime.CompilerServices नाम स्थान में CallerFilePath , CallerMethodName और CallerLineNumber विशेषताओं पर । उदाहरण के लिए:

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

तर्क होना चाहिए stringके लिए CallerMemberNameऔर CallerFilePathऔर एक intके लिएCallerLineNumber होना चाहिए और एक डिफ़ॉल्ट मान होना चाहिए। विधि मापदंडों पर इन विशेषताओं को निर्दिष्ट करने से संकलनकर्ता को संकलन समय में कॉलिंग कोड में उचित मूल्य सम्मिलित करने का निर्देश मिलता है, जिसका अर्थ है कि यह ओफ़्फ़्यूशन के माध्यम से काम करता है। अधिक जानकारी के लिए कॉलर जानकारी देखें ।


@MonsterMMORPG यह चाहे कोई त्रुटि हो या न हो, काम करता है। StackFrame वर्ग वर्तमान को निष्पादित करने वाली पद्धति को देख रहा है। StackFrame कंस्ट्रक्टर के लिए पहला तर्क कॉल गहराई (1) है और दूसरा तर्क इंगित करता है कि फ़ाइल जानकारी की आवश्यकता है।
22

3
यदि आप मोनोStackFrame पर उदाहरण संकलित कर रहे हैं , तो संकलन समय और रन समय पर उपयोग करना सुनिश्चित करें--debug
बर्नार्ड पल्स

StackFrame.NET Core में उपलब्ध नहीं है। मार्क ग्रेवेल के उत्तर का उपयोग करें।
जेसी चिशोल्म

डिफ़ॉल्ट मान का उपयोग करना = string.Emptyत्रुटि "कॉलिंग फ़ाइलपैथ के लिए डिफ़ॉल्ट पैरामीटर मान" एक संकलन-समय स्थिर होना चाहिए " !
stomy

1
@stomy मैंने बदले में दोहरे उद्धरण चिह्नों ( "") का उपयोग करने के लिए परीक्षा [le को बदल दिया string.Empty
एकटन

21

मुझे एक लाइनर पसंद है:

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

8
इसे .pdb फ़ाइल की आवश्यकता है .. जिसे हम आम तौर पर उत्पादन सर्वर में उत्पन्न / कॉपी नहीं करते हैं।
दीपक शर्मा

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

आउटपुट:

शून्य परीक्षण () (FILENAME.cs: 104)

इधर देखो!

Console.WriteLine स्वरूप को आप कैसे पसंद करते हैं बदलें


3
सभी मामलों में काम नहीं करेगा .. इसे हमेशा .pdb फ़ाइल की आवश्यकता होती है, जिसे हम आम तौर पर उत्पादन सर्वर में उत्पन्न / कॉपी नहीं करते हैं। C # 5.0 कॉलर * विशेषता के साथ प्रयास करें।
दीपक शर्मा

2
यदि आप इसके बजाय इसका उपयोग करते हैं: System.Diagnostics.Debug.WriteLine(String.Format("{0}({1}): {2}: {3}", fileName, lineNumber, methodName, message));तो आप आउटपुट विंडो में लाइन पर क्लिक कर सकते हैं और स्रोत में उस लाइन पर ले जाया जा सकता है।
जेसी चिशोल्म

3

अगर इसकी एक कोशिश पकड़ने ब्लॉक में इस का उपयोग करें।

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() करेंगे तो आपके पास वर्तमान लाइन होगी। स्टैकट्रेस के उपयोग से किसी भी समाधान पर यह लाभ है कि इसे डिबग और रिलीज़ दोनों में काम करना चाहिए।

इसलिए जो आवश्यक है उसका मूल अनुरोध लेना, यह बन जाएगा:

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

यह मार्क ग्रेवेल के उत्कृष्ट जवाब पर बन रहा है।


इससे सही लाइन नंबर वापस नहीं आता है। मुझे किसी कारण से इसे ठीक करने के लिए 191 को घटाना होगा।
डैनियल

दिलचस्प। मेरे लिए यहाँ ठीक काम करता है। क्या आपके पास IDE में लिंक नंबर चालू हैं? यदि आप इस फ़ंक्शन को फ़ाइल में विभिन्न स्थानों से कॉल करते हैं, तो क्या आपको अभी भी 191 घटाना है? यह या तो आपके पेज पर एक कंपाइलर बग (असंभावित, लेकिन संभव हो सकता है) या एक ढहने वाला ब्लॉक होगा (जबकि जो लाइन नंबरों को सही होने से नहीं रोक सकता है वह अंतर को समझा सकता है यदि आप लाइन नंबर देखने के बजाय गिन रहे थे)। यदि आप मुझसे ऑफ़लाइन संपर्क कर सकते हैं तो मुझे इसकी तह तक जाना अच्छा लगेगा।
ब्रायन क्राइजर

कोई ढहने वाले ब्लॉक, लाइन नंबर चालू नहीं हैं, फिर भी 191 को घटाना होगा, भले ही इसका नाम कहां से हो। मुझे पता है ... अजीब।
डेनियल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.