Short answer:
It will display the value 11. The value 21 would never be displayed because the catch block runs only when there is an exception.
Long answer
Come on, directly from the MSDN
When an exception is thrown, the common language runtime (CLR) looks
for the catch statement that handles this exception. If the currently
executing method does not contain such a catch block, the CLR looks at
the method that called the current method, and so on up the call
stack If no catch block is found, then the CLR displays an unhandled
exception message to the user and stops execution of the program.
That is, when an exception is raised, the CLR looks for the closest catch from where this exception was raised and executes its block of code. This means that if the current block of code where the exception was raised does not have a catch
, this catch
will be searched in the methods that called it until it reaches the top of the call stack, where an exception of type Unhandled Exception
for the user, stopping the execution of the program.
Then ...
The rest of the code within a try runs after
find an exception or jump directly to the code inside the
catch (Exception e)
The try
block contains code that can raise an exception, and it will run while there is no exception or until it is terminated . In other words, if an exception occurs, it will look directly at the nearest catch without executing the rest of the code inside the block try
.
The try block contains the guarded code that may cause the exception.
The block is executed until an exception is thrown or completed
successfully. For example, the following attempt to cast a null object
raises the NullReferenceException exception:
Why this behavior?
An exception indicates that something unusual occurred during the execution of your code. If "something wrong" occurred during this run, do you want the rest of your code to run normally? The block catch
must be used just to execute a specific code for these abnormal cases, when you know they can happen .
The catch block can be used in several ways, as can be seen below:
catch(InvalidOperationException ex)
{
//Deve ser executado quando uma exceção do tipo InvalidOperationException seja levantada
}
catch(SqlException ex) when (ex.Message.Contains("TIMEOUT"))
{
//Deve capturar uma exceção do tipo SqlException e que contenha no message a palavra TIMEOUT
}
catch(Exception ex)
{
//Deve capturar uma exceção que não seja uma InvalidOperationException ou **SqlException que não contenha** no message a palavra TIMEOUT
}
Avoid catching generic (Exception ex)
exceptions in your application-specific code unless you know what you're doing (logging at the highest point on the system, for example), or raise it again with a throw
or by placing it as a Inner Exception
. Finally, there are some exception categories that you can use to guide yourself on your treatment:
-
Usage errors: A usage error represents an error in program logic
which may result in an exception. However, this type of error should not
be resolved with a block
try catch
, but with a change in the
code to be executed. It's a mistake that you know will happen and
which can be avoided .
-
Program error: A runtime error that can not be avoided when building code can fall into this category. Imagine that you need to read a file in a specific directory. In order not to fall into Usage error , you first check if this file exists so you can use it. However, although the check returned true for the existence of the file, at the time of reading it was found unavailable (was deleted or being used by another process) , raising an exception from
FileNotFoundException
, or similar.
-
System failures: System failures are exceptions that can occur at runtime and can not normally be handled very effectively. What can you as a developer do if a
OutOfMemoryException
is raised? You can, however, log the information for this exception in a log before the application is terminated for further analysis to prevent this error from occurring again.
Recommended Readings