दरअसल, कुछ स्थितियां ऐसी होती हैं, जो throw
स्टैकट्रेस जानकारी को संरक्षित नहीं करती हैं। उदाहरण के लिए, नीचे दिए गए कोड में:
try
{
int i = 0;
int j = 12 / i; // Line 47
int k = j + 1;
}
catch
{
// do something
// ...
throw; // Line 54
}
स्टैकट्रेस संकेत देगा कि रेखा 54 ने अपवाद को उठाया, हालांकि इसे 47 की रेखा पर उठाया गया था।
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.
at Program.WithThrowIncomplete() in Program.cs:line 54
at Program.Main(String[] args) in Program.cs:line 106
ऊपर वर्णित स्थितियों की तरह, मूल स्टैकट्रेस को preseve करने के लिए दो विकल्प हैं:
अपवाद कह रहे हैं। InternalPreserveStackTrace
जैसा कि यह एक निजी तरीका है, इसे प्रतिबिंब का उपयोग करके लागू करना होगा:
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
स्टैकट्रेस जानकारी को संरक्षित करने के लिए मेरे पास एक निजी पद्धति पर निर्भर होने का नुकसान है। इसे .NET फ्रेमवर्क के भविष्य के संस्करणों में बदला जा सकता है। ऊपर दिए गए कोड का उदाहरण और नीचे प्रस्तावित समाधान Fabrice MARGUERIE वेबलॉग से निकाला गया था ।
कॉलिंग अपवाद। SetObjectData
नीचे दी गई तकनीक में एंटोन टायखी द्वारा इन सी # के जवाब के रूप में सुझाव दिया गया था , स्टैक ट्रेस प्रश्न को खोए बिना मैं इनरसेप्शन को कैसे पुनर्व्यवस्थित कर सकता हूं ।
static void PreserveStackTrace (Exception e)
{
var ctx = new StreamingContext (StreamingContextStates.CrossAppDomain) ;
var mgr = new ObjectManager (null, ctx) ;
var si = new SerializationInfo (e.GetType (), new FormatterConverter ()) ;
e.GetObjectData (si, ctx) ;
mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData
mgr.DoFixups () ; // ObjectManager calls SetObjectData
// voila, e is unmodified save for _remoteStackTraceString
}
हालाँकि, इसे सार्वजनिक तरीकों पर भरोसा करने का फायदा है, यह केवल निम्न अपवाद निर्माणकर्ता पर निर्भर करता है (जो कि 3 पार्टियों द्वारा विकसित कुछ अपवाद लागू नहीं होते हैं):
protected Exception(
SerializationInfo info,
StreamingContext context
)
मेरी स्थिति में, मुझे पहला दृष्टिकोण चुनना था, क्योंकि मैं जिस 3-पार्टी लाइब्रेरी का उपयोग कर रहा था, उसके अपवादों को इस निर्माता ने लागू नहीं किया था।