Sebenarnya, ada beberapa situasi dimana throw
statment tidak akan menyimpan informasi StackTrace. Misalnya, dalam kode di bawah ini:
try
{
int i = 0;
int j = 12 / i; // Line 47
int k = j + 1;
}
catch
{
// do something
// ...
throw; // Line 54
}
StackTrace akan menunjukkan bahwa baris 54 menaikkan pengecualian, meskipun itu dinaikkan pada baris 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
Dalam situasi seperti yang dijelaskan di atas, ada dua opsi untuk preseve StackTrace asli:
Memanggil Exception.InternalPreserveStackTrace
Karena ini adalah metode pribadi, itu harus dipanggil dengan menggunakan refleksi:
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
Saya memiliki kelemahan mengandalkan metode pribadi untuk menjaga informasi StackTrace. Itu bisa diubah di versi .NET Framework. Contoh kode di atas dan solusi yang diusulkan di bawah ini diambil dari weblog Fabrice MARGUERIE .
Memanggil Exception.SetObjectData
Teknik di bawah ini disarankan oleh Anton Tykhyy sebagai jawaban untuk In C #, bagaimana saya bisa memikirkan kembali InnerException tanpa kehilangan pertanyaan susunan jejak .
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
}
Meskipun, memiliki keuntungan mengandalkan metode publik hanya itu juga tergantung pada konstruktor pengecualian berikut (yang beberapa pengecualian yang dikembangkan oleh pihak ke-3 tidak diterapkan):
protected Exception(
SerializationInfo info,
StreamingContext context
)
Dalam situasi saya, saya harus memilih pendekatan pertama, karena pengecualian yang diajukan oleh perpustakaan pihak ketiga yang saya gunakan tidak menerapkan konstruktor ini.