Faced with code that make one exception instance and then probably throw it multiple times.
private readonly Exception exceptionInstance = new Exception("message");
Is it correct to throw same exception instance multiple times?
Faced with code that make one exception instance and then probably throw it multiple times.
private readonly Exception exceptionInstance = new Exception("message");
Is it correct to throw same exception instance multiple times?
It's bad practice for various already stated reasons, but it will fail especially hard in multithreaded code, because Exception
class is (obviously) not thread safe, and it's not immutable.
Consider this code:
class Program {
static readonly Exception _test = new Exception("test");
static void Main(string[] args) {
ThreadPool.SetMinThreads(10, 8);
var random = new Random();
int num1 = 0;
int num2 = 0;
var tasks = new List<Task>();
for (int i = 0; i < 10; i++) {
tasks.Add(Task.Run(() => {
try {
if (random.Next(0, 2) == 0) {
Interlocked.Increment(ref num1);
Throw1();
}
else {
Interlocked.Increment(ref num2);
Throw2();
}
}
catch (Exception ex) {
Console.WriteLine(ex);
}
}));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("num1: " + num1);
Console.WriteLine("num2: " + num2);
Console.ReadKey();
}
static void Throw1() {
throw _test;
}
static void Throw2() {
throw _test;
}
}
Here we have 2 methods, Throw1()
and Throw2()
which both throw the same instance of exception from private field. Then we run 10 threads which call either Throw1()
or Throw2()
randomly and print what has been thrown. Example output of such code is:
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
System.Exception: test
в ConsoleApp8.Program.Throw1() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 52
в ConsoleApp8.Program.<>c__DisplayClass1_0.<Main>b__0() в H:\VSProjects\SoHelp\ConsoleApp8\Program.cs:строка 32
num1: 6
num2: 4
So while Throw1()
has been called 6 times and Throw2()
has been called 4 times - all 10 stack traces we printed refer to Throw1()
method.
So just don't ever do that, because there is absolutely no reasons to.
No. Throwing the same instance of Exception
from multiple places in your code (not counting rethrows!) is not recommended.
An Exception contains more then just it's message - it contains valuable information for debugging such as the stack trace. (Update: just tested that now. the stack trace is probably added to the exception in the throw statement, so it's not relevant to this answer) and TargetSite (from my tests, seems like it is being populated the first time the exception is thrown, but never again after that).
Throwing the same instance of Exception
in different places in your code would deny you the ability to use some of this data.