En teoría, un bloque try / catch no tendrá efecto en el comportamiento del código a menos que realmente ocurra una excepción. Sin embargo, hay algunas circunstancias excepcionales en las que la existencia de un bloque try / catch puede tener un efecto importante, y algunas infrecuentes pero apenas oscuras en las que el efecto puede ser notable. La razón de esto es ese código dado como:
Action q;
double thing1()
{ double total; for (int i=0; i<1000000; i++) total+=1.0/i; return total;}
double thing2()
{ q=null; return 1.0;}
...
x=thing1(); // statement1
x=thing2(x); // statement2
doSomething(x); // statement3
el compilador puede optimizar la declaración1 basándose en el hecho de que la declaración2 está garantizada para ejecutarse antes que la declaración3. Si el compilador puede reconocer que thing1 no tiene efectos secundarios y que thing2 realmente no usa x, puede omitir de manera segura thing1 por completo. Si [como en este caso] thing1 fuera costoso, eso podría ser una optimización importante, aunque los casos en que thing1 es costoso también son los que el compilador sería menos probable que optimice. Supongamos que el código fue cambiado:
x=thing1(); // statement1
try
{ x=thing2(x); } // statement2
catch { q(); }
doSomething(x); // statement3
Ahora existe una secuencia de eventos donde la instrucción3 podría ejecutarse sin que la instrucción2 se haya ejecutado. Incluso si nada en el código para thing2
podría arrojar una excepción, sería posible que otro subproceso pudiera usar un Interlocked.CompareExchange
para notar que q
se borró y establecerlo Thread.ResetAbort
, y luego realizar una Thread.Abort()
instrucción anterior2 en la que escribió su valor x
. Luego, catch
se ejecutaría Thread.ResetAbort()
[a través del delegado q
], permitiendo que la ejecución continúe con la instrucción3. Tal secuencia de eventos sería, por supuesto, excepcionalmente improbable, pero se requiere un compilador para generar código que funcione de acuerdo con las especificaciones, incluso cuando ocurran tales eventos improbables.
En general, es mucho más probable que el compilador note oportunidades de omitir bits de código simples que los complejos, y por lo tanto, sería raro que un try / catch pueda afectar mucho el rendimiento si nunca se lanzan excepciones. Aún así, hay algunas situaciones en las que la existencia de un bloque try / catch puede evitar optimizaciones que, de no ser por el try / catch, hubieran permitido que el código se ejecute más rápido.