Інші відповіді цілком правильні, але ця відповідь дає деякі додаткові відомості.
Розглянемо цей приклад:
using System;
static class Program {
static void Main() {
try {
ThrowTest();
} catch (Exception e) {
Console.WriteLine("Your stack trace:");
Console.WriteLine(e.StackTrace);
Console.WriteLine();
if (e.InnerException == null) {
Console.WriteLine("No inner exception.");
} else {
Console.WriteLine("Stack trace of your inner exception:");
Console.WriteLine(e.InnerException.StackTrace);
}
}
}
static void ThrowTest() {
decimal a = 1m;
decimal b = 0m;
try {
Mult(a, b); // line 34
Div(a, b); // line 35
Mult(b, a); // line 36
Div(b, a); // line 37
} catch (ArithmeticException arithExc) {
Console.WriteLine("Handling a {0}.", arithExc.GetType().Name);
// uncomment EITHER
//throw arithExc;
// OR
//throw;
// OR
//throw new Exception("We handled and wrapped your exception", arithExc);
}
}
static void Mult(decimal x, decimal y) {
decimal.Multiply(x, y);
}
static void Div(decimal x, decimal y) {
decimal.Divide(x, y);
}
}
Якщо ви коментуєте throw arithExc;
рядок, ваш результат:
Handling a DivideByZeroException.
Your stack trace:
at Program.ThrowTest() in c:\somepath\Program.cs:line 44
at Program.Main() in c:\somepath\Program.cs:line 9
No inner exception.
Звичайно, ви втратили інформацію про те, де сталося це виключення. Якщо замість цього ви використовуєте throw;
рядок, ви отримуєте ось що:
Handling a DivideByZeroException.
Your stack trace:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
at Program.ThrowTest() in c:\somepath\Program.cs:line 46
at Program.Main() in c:\somepath\Program.cs:line 9
No inner exception.
Це набагато краще, тому що зараз ви бачите, що саме Program.Div
метод викликав у вас проблеми. Але все ще важко зрозуміти, чи виникає ця проблема з лінії 35 або лінії 37 в try
блоці.
Якщо ви використовуєте третю альтернативу, завернувши зовнішній виняток, ви втрачаєте інформацію:
Handling a DivideByZeroException.
Your stack trace:
at Program.ThrowTest() in c:\somepath\Program.cs:line 48
at Program.Main() in c:\somepath\Program.cs:line 9
Stack trace of your inner exception:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
at Program.ThrowTest() in c:\somepath\Program.cs:line 35
Зокрема, ви бачите, що саме ця проблема призводить до лінії 35 . Однак для цього потрібні люди шукати InnerException
, і внутрішні винятки у простих випадках відчувають дещо опосередкованим.
У цій публікації щоденника вони зберігають номер рядка (рядок блоку спробу), викликаючи (через відображення) internal
метод примірника InternalPreserveStackTrace()
на Exception
об’єкт. Але недобре використовувати таке відображення (.NET Framework може змінити своїх internal
членів якось без попередження).