จริงๆแล้วมีบางสถานการณ์ที่throw
statment จะไม่เก็บข้อมูล StackTrace ตัวอย่างเช่นในรหัสด้านล่าง:
try
{
int i = 0;
int j = 12 / i; // Line 47
int k = j + 1;
}
catch
{
// do something
// ...
throw; // Line 54
}
StackTrace จะระบุว่าบรรทัด 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 StackTrace ดั้งเดิม:
เรียก Exception.InternalPreserveStackTrace
เนื่องจากเป็นวิธีส่วนตัวจึงต้องเรียกใช้โดยใช้การสะท้อนภาพ:
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
ผมมีข้อเสียของการอาศัยวิธีการส่วนตัวเพื่อรักษาข้อมูล StackTrace ที่ สามารถเปลี่ยนแปลงได้ใน. NET Framework รุ่นอนาคต ตัวอย่างรหัสข้างต้นและโซลูชั่นที่นำเสนอดังต่อไปนี้ถูกสกัดจากFabrice MARGUERIE เว็บบล็อก
การเรียกข้อยกเว้น SetObjectData
เทคนิคด้านล่างนี้ได้รับการแนะนำโดยAnton Tykhyyเป็นคำตอบสำหรับใน C # ฉันจะสร้าง InnerException ใหม่ได้อย่างไรโดยไม่สูญเสียคำถามการติดตามสแต็ก
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
}
แม้ว่าจะมีข้อได้เปรียบของการใช้วิธีการสาธารณะเท่านั้น แต่ยังขึ้นอยู่กับตัวสร้างข้อยกเว้นต่อไปนี้ (ซึ่งข้อยกเว้นบางอย่างที่พัฒนาโดยบุคคลที่สามไม่ได้ใช้):
protected Exception(
SerializationInfo info,
StreamingContext context
)
ในสถานการณ์ของฉันฉันจะต้องเลือกวิธีแรกเพราะข้อยกเว้นที่เกิดขึ้นโดยห้องสมุดของบุคคลที่ 3 ผมใช้ไม่ได้ใช้คอนสตรัคนี้