Exception handling best practices in C#
Errors in any language are classified into Compile Time Errors, Runtime Errors and Logical Errors.
Compile Time Errors
Compile time errors are the errors that are found during compilation. In general, these errors are syntactical errors in the program. It is not possible to execute the program without rectifying the compile time errors. Hence exception handling is not related to compile time errors.
Runtime Errors
Runtime errors are the errors that occur at runtime i.e., while executing the program. These are also called exceptions. When an exception occurs, then the program will be terminated abnormally without giving a proper message to the user regarding the exception. Exception handling is used to handle exceptions and give a proper message to the user regarding exception and avoid abnormal termination of the program. Exception handling in C# was based on the keywords try
, catch
, finally
and throw
.
Try
block is used to write the statements that may cause an exception. When an exception was raised in the try block, control will be taken to catch
block where we have to write the exception handling code. Once control reaches the catch
block, it is not possible to take it back to try
. The complete code in the try
block will be executed only when there is no exception raised, and the code in the catch
block is executed only when an exception was raised. But you may have the code to be executed both when an exception was raised, and no exception was raised.
Finally
block is used to write the code that needs to be executed both when an exception was raised and no exception was raised.
Throw
is used to raise the exceptions manually.
try
{
}
catch
{
}
finally
{
}
Example :
The following example accepts two integers and performs division. If the value given for the denominator is zero, then an exception will be raised, and the program handles this exception with exception handling.
namespace ExceptionHandling
{
class Program
{
static void Main(string[] args)
{
int A, B, R;
Console.WriteLine("Enter Two Integers");
A = int.Parse(Console.ReadLine());
B = int.Parse(Console.ReadLine());
try
{
R = A / B;
Console.WriteLine("Ratio Of {0} And {1} Is {2}", A, B, R);
}
catch (DivideByZeroException Ex)
{
Console.WriteLine("Division With Zero Not Possible");
}
}
}
}
Handling Multiple Exceptions
Within a method, there is a possibility for more than one exception. In this case no need to write separate try…catch
for each exception and related to a single try
block, you can create any number of catch
blocks, one for each type of exception.
Example :
The following example handles two exceptions divided by zero exception and overflow exception that will be raised when the variable's value is out of range for its data type.
namespace ExceptionHandling
{
class MultipleExceptions
{
static void Main()
{
int A, B, R;
Console.WriteLine("Enter Two Integers")
try
{
A = int.Parse(Console.ReadLine());
B = int.Parse(Console.ReadLine());
R = A / B;
Console.WriteLine("Ratio Of {0} And {1} Is {2}", A, B, R);
}
catch (DivideByZeroException Ex)
{
Console.WriteLine("Division With Zero Not Possible");
}
catch (OverflowException Ex)
{
Console.WriteLine("Value Must Be Within The Range Of Integer");
}
catch (FormatException Ex)
{
Console.WriteLine("Value Must Be Numeric");
}
Console.Read();
}
}
}
Handling Any Type of Exception
A programmer will write the exception handling code for all the exceptions that are up to his expectation. But there is a possibility for an exception that was not up to the expectation of the programmer. Hence, exception handling will be complete only when a catch block can catch any exception. For this, you have to create the catch block by specifying the exception type as an Exception. Every exception in .NET is inherited from the Exception class, and hence it can catch any exception. This type of catch
block must be the last catch
in a series of catch
blocks.
Example :
The following example handles three exceptions DivideByZeroException
, OverflowException
, and FormatException
, and can also handle any other type of exception.
namespace ExceptionHandling
{
class AnyException
{
static void Main()
{
int A, B, R;
Console.WriteLine("Enter Two Integers");
try
{
A = int.Parse(Console.ReadLine());
B = int.Parse(Console.ReadLine());
R = A / B;
Console.WriteLine("Ratio Of {0} And {1} Is {2}", A, B, R);
}
catch (DivideByZeroException Ex)
{
Console.WriteLine("Division With Zero Not Possible");
}
catch (OverflowException Ex)
{
Console.WriteLine("Value Must Be Within The Range Of Integer");
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message);
}
Console.Read();
}
}
}
User Defined Exceptions
There may be a situation where the system will not raise an exception for your requirement, and you want to raise the exception manually. In this case, you have to create a class for your exception, and it must be inherited from the Exception class. To raise the exception, use the throw
keyword.
Example :
The following example creates a user-defined exception to raise an exception when a user enters a negative value for either A or B.
namespace ExceptionHandling
{
class MyException : Exception
{
public string MyMessage;
public MyException(string Mes)
{
MyMessage = Mes;
}
}
class UserExceptions
{
static void Main()
{
int A, B, R;
Console.WriteLine("Enter Two Integers");
try
{
A = int.Parse(Console.ReadLine());
if(A < 0)
throw new MyException("-ve Values Are Not Allowed");
B = int.Parse(Console.ReadLine());
if(B<0)
throw new MyException("-ve Values Are Not Allowed");
R = A / B;
Console.WriteLine("Ratio Of {0} And {1} Is {2}", A, B, R);
}
catch (DivideByZeroException Ex)
{
Console.WriteLine("Division With Zero Not Possible");
}
catch (OverflowException Ex)
{
Console.WriteLine("Value Must Be Within The Range Of Integer");
}
catch(MyException Ex)
{
Console.WriteLine(Ex.MyMessage);
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message);
}
Console.Read();
}
}
}
Logical Errors
The logical error is an error that will not be found during compilation or at runtime and will cause the program output to be wrong. To find and rectify the logical errors tracing and debugging are used. Executing the program step by step and finding logical errors is called tracing and debugging. F10 and F11 keys are used to execute the program step by step.
Break Point
When you don’t want to execute the entire program step by step and execute only a particular method step by step, then breakpoints are used. When a breakpoint is placed in the program, then during execution, when control reaches the breakpoint, then the program will enter into debug mode, and from there, you can execute the program step by step. A shortcut to place or remove a breakpoint is F9.
Debug Tools
For debugging a .NET application, debugging tools are provided and are as follows.
Watch Window :
This can be used to add a variable to it and observe how the value of that variable changes while executing the program step by step. VS.net provides four watch windows, and shortcuts to open watch windows are
- CTRL + ALT + W, 1
- CTRL + ALT + W, 2
- CTRL + ALT + W, 3
- CTRL + ALT + W, 4
For adding a variable to the watch window, select the variable, right-click on it, and then choose to Add to watch. Otherwise, select the variable and drag and drop it in the watch window. You can also modify the value of a variable in the watch window. For this, right-click on the variable in the watch window and choose edit value.
Locals Window :
This is used to observe how the values of local variables of the current method are changed as the program is executed step by step. There is no need to add variables to the locals window, and all local variables of the current method are automatically added to the locals window. Shortcut to open locals window is CTRL + ALT + V
, L
. Same as the watch window, in the locals window, you can edit the value of a variable.
Immediate Window :
This is used to print the values of variables or expressions and even change the values of variables. “?” is used to print the value of a variable or expression within the immediate window. To change the value of a variable, write the assignment statement. Shortcut to open immediate window is CTRL + ALT + I
. Advantage of this is you can execute your expressions, and it is available even at design time. But watch and locals windows are available only at runtime, and they can be used only to observe values of variables, and we can't write our expressions.
-
CreatedOct 21, 2014
-
UpdatedNov 03, 2020
-
Views1,832