Skip to main content

Using try/catch/finally --- Exception Handling

Introduction


Software Programmers write code to perform some desired actions. But every software may fail to perform its desired actions under some of its internal or external failures. The exception handling system in the C# language allows the programmer to handle errors or anomalous situations in a structured manner that allows the programmer to separate the normal flow of the code from error-handling logic.

An exception can represent a variety of abnormal conditions that arise from several possible external or internal conditions of software application. External conditions of execution failures includes, for example, network failures in connecting to a remote component, inadequate rights in using a file/system resource, out of memory exception or exception thrown by a web service etc. These are mainly due to failures thrown by environment components on which our application depends on e.g. operating system, .net runtime or external application or components. Internal failures may be due to software defects, designed functional failures (failures required as per business rules), propagated external failures e.g. a null object reference detected by the runtime, or an invalid input string entered by a user and detected by application code, user requesting to withdraw more amount than the account balance(business rule).


Note: A must read para is below

Code that detects an error condition is said to throw an exception and code that handles the error is said to catch the exception. An exception in C# is an object that encapsulates various information about the error that occurred, such as the stack trace at the point of the exception and a descriptive error message. All exception objects are instantiations of the System.Exception or a child class of it. There are many exception classes defined in the .NET Framework used for various purposes. Programmers may also define their own class inheriting from System.Exception or some other appropriate exception class from the .NET Framework.


Overview


There are three code definitions for exception handling. These are:
  • try/catch - Do something and catch an error, if it should occur.
  • try/catch/finally - Do something and catch an error if it should occur, but always do the finally.
  • try/finally - Do something, but always do the finally. Any exception that occurs, will be thrown after finally.
Exceptions are caught from most specific, to least specific. So for example, if you try and access a file that does not exist, the CLR would look for exceptions in the following order:
  • FileNotFoundException
  • IOException (base class of FileNotFoundException)
  • SystemException (base class of IOException)
  • Exception (base class of SystemException)
If the exception being thrown does not derive or is not in the list of exceptions to catch, it is thrown up the call stack.



Examples

try/catch

The try/catch performs an operation and should an error occur, will transfer control to the catch block, should there be a valid section to be caught by:

class ExceptionTest
{
     public static void Main(string[] args)
     {
          try
          {
               Console.WriteLine(args[0]);
               Console.WriteLine(args[1]);
               Console.WriteLine(args[2]);
               Console.WriteLine(args[3]);
               Console.WriteLine(args[4]);
          }
          catch (ArgumentOutOfRangeException e)
          {
               Console.WriteLine(e.Message);
          }
     }
} 
 
Here is an example with multiple catches:

class ExceptionTest
{
     public static void Main(string[] args)
     {
          try
          {
               string fileContents = new StreamReader(@"C:\log.txt").ReadToEnd();
          }
          catch (UnauthorizedAccessException e) // Access problems
          {
               Console.WriteLine(e.Message);
          }
          catch (FileNotFoundException e)       // File does not exist
          {
               Console.WriteLine(e.Message);
          }
          catch (IOException e)                // Some other IO problem.
          {
               Console.WriteLine(e.Message);
          }
     }
} 
 
In all catch statements you may omit the type of exception and the exception variable name:
try
{
    int number = 1/0;
}
catch (DivideByZeroException)
{
    // DivideByZeroException
}
catch
{
    // some other exception
}

try/catch/finally

Catching the problem is a good idea, but it can sometimes leave your program in an invalid state. For example, if you open a connection to a database, an error occurs and you throw an exception. Where would you close the connection? In both the try AND exception blocks? Well, problems may occur before the close is carried out.
Therefore, the finally statement allows you to cater for the "in all cases do this" circumstance. See the example below:

using System;
class ExceptionTest
{
     public static void Main(string[] args)
     {
          SqlConnection sqlConn = null;
 
          try
          {
              sqlConn = new SqlConnection ( /*Connection here*/ );
              sqlConn.Open();
 
              // Various DB things
 
              // Notice you do not need to explicitly close the connection, as .Dispose() does this for you.
          }
          catch (SqlException e)
          {
               Console.WriteLine(e.Message);
          }
          finally
          {
               if (sqlConn != null && sqlConn.State != ConnectionState.Closed)
               {
                   sqlConn.Dispose();
               }
          }
     }
} 
 
Second Example
using System;
public class excepation
{
        public double num1, num2,result;
 
        public void add()
        {
                try
                {
                        Console.WriteLine("enter your number");
                        num1 = Convert.ToInt32(Console.ReadLine());
                        num2 = Convert.ToInt32(Console.ReadLine());
                        result = num1/num2;
                }
                catch(DivideByZeroException  e) //FormatException
                {
                        Console.WriteLine("{0}",e.Message);
                }
                catch(FormatException ex)
                {
                        Console.WriteLine("{0}",ex.Message);
                }
                finally
                {
                        Console.WriteLine("turn over");
                }
        }
        public void display()
        {
                Console.WriteLine("The Result is: {0}",result);
        }
        public static void Main()
        {
                excepation ex = new excepation();
                ex.add();
                ex.display();
        }       
}
Notice that the SqlConnection object is declared outside of the try/catch/finally. The reason is that anything declared in the try/catch cannot be seen by the finally. By declaring it in the previous scope, the finally block is able to access it.

try/finally

The try/finally block allows you to do the same as above, but instead errors that are thrown are dealt with by the catch (if possible) and then thrown up the call stack.
class ExceptionTest
{
     public static void Main(string[] args)
     {
          SqlConnection sqlConn = null;
 
          try
          {
              SqlConnection sqlConn = new SqlConnection ( /*Connection here*/ );
              sqlConn.Open();
 
              // Various DB bits
          }
          finally
          {
               if (sqlConn != null && sqlConn.State != ConnectionState.Closed)
               {
                   sqlConn.Dispose();
               }
          }
     }
}

Re-throwing exceptions

Sometimes it is better to throw the error up the call stack for two reasons.
  1. It is not something you would expect to happen.
  2. You are placing extra information into the exception, to help diagnosis.

How not to throw exceptions

Some developers write empty try/catch statements like this:
try
{
      // Do something
}
catch (Exception ex)
{
      // Ignore this here
}
This approach is not recommended. You are swallowing the error and continuing on. If this exception was an OutOfMemoryException or a NullReferenceException, it would not be wise to continue. Therefore you should always catch what you would expect to occur, and throw everything else.
Below is another example of how to incorrectly catch exceptions

/* Read the config file, and return the integer value. If it does not exist, then this is a problem! */
 
try
{
     string value = ConfigurationManager.AppSettings["Timeout"];
 
     if (value == null)
         throw new ConfigurationErrorsException("Timeout value is not in the configuration file.");
}
catch (Exception ex)
{
     // Do nothing!
}
As you can see, the ConfigurationErrorsException will be caught by the catch (Exception) block, but it is being ignored completely! This is bad programming as you are ignoring the error.
Some developers believe you should also use:
try
{
   ..
}
catch (Exception ex)
{
     throw ex;
}
This is incorrect. What is happening is that the CLR will now think that the throw ex; statement is the source of the problem, when the problem is actually in the try section. Therefore never re-throw in this way.

How to catch exceptions

A better approach would be:
/* Read the config file, and return the integer value. If it does not exist, then this is a problem! */
 
try
{
     string value = ConfigurationManager.AppSettings["Timeout"];
 
     if (value == null)
         throw new ConfigurationErrorsException("Timeout value is not in the configuration file.");
}
catch (Exception ex )
{
     throw; // <-- Throw the existing problem!
}
The throw; keyword means preserve the exception information and throw it up the call stack.

Extra information within exceptions

An alternative is to give extra information (maybe local variable information) in addition to the exception. In this case, you wrap the exception within another. You usually use an exception that is as specific to the problem as possible, or create your own, if you cannot find out that is not specific enough (or if there is extra information you would wish to include).
public OrderItem LoadItem(string itemNumber)
{
    DataTable dt = null;
 
    try
    {
         if (itemNumber == null)
              throw new ArgumentNullException("Item Number cannot be null","itemNumber");
 
         DataTable dt = DataAccess.OrderItem.Load(itemNumber);
 
         if (dt.Rows == 0)
              return null;
         else if (dt.Rows > 1)
              throw new DuplicateDataException( "Multiple items map to this item.",itemNumber, dt);
 
         OrderItem item = OrderItem.CreateInstanceFromDataRow(dt.Rows[0]);
 
         if (item == null)
              throw new ErrorLoadingException("Error loading Item " + itemNumber, itemNumber, dt.Rows[0]);
    }
    catch (DuplicateDataException dde)
    {
         throw new ErrorLoadingException("OrderItem.LoadItem failed with Item " + 
                                                            itemNumber, dde); // <-- Include dde (as the InnerException) parameter
    }
    catch (Exception ex)
    {
         throw; // <-- We aren't expecting any other problems, so throw them if they occur.
    }
}


Thank you. I hope things are pretty clear here.

Comments

Popular posts from this blog

Convert your datatable into generic poco object in c# using linq, ado and reflections.

Follow @harshit_parshii The most common problem that we face these days is to create a common class and method that can be used across all the projects and codes. So today I will be sharing my code where you can see how to make and create a generic function without using entity framework for ado. net. The scenario is like you have an old software that uses stored procedure to return set of entities as a data-table, you do not want to re-write the back-end code as you are creating a web API in c# which needs to be delivered asap. You need to map these data tables to models as you might be using MV* pattern. So here we will be doing one to one mapping of model to data- table, and in similar fashion insert or update can also be done. So basically we are converting a data-table to list of strongly typed object model to do CRUD operations. So we have following things before hand. A helper class is referenced as the database(dbFactory) which executes ado. ne...

Send a Fax in windows using faxcomexlib and TAPI in VB code .Net

An application that provides sending fax from faxmodem, connected to the computer, will be explained in the following post.  We can use Telephony Application Programming Interface (TAPI) and the Fax Service Extended Component Object Model (COM) API to send fax. The fax service is a Telephony Application Programming Interface (TAPI)-compliant system service that allows users on a network to send and receive faxes from their desktop applications. The service is available on computers that are running Windows 2000 and later. The fax service provides the following features: Transmitting faxes Receiving faxes Flexible routing of inbound faxes Outbound routing Outgoing fax priorities Archiving sent and received faxes Server and device configuration management Client use of server devices for sending and receiving faxes Event logging Activity logging Delivery receipts Security permissions The following Microsoft Visual Basic code example sends a fax. Note that...

DTMF (Mobile) based speed control of AC motor.

Introduction: With the advancement of ages from prehistoric to present day scenario our life has become more sophisticated and busy, so to ease the schedule of this busy life, technology has play the vital role in it and for its proper running of machine the technology has gone further by providing digitization of analog machinery and its use is enhanced day by day. This project is based on the same concept by wireless controlling the machinery through mobile system anywhere from the world. This project aims at Speed Control of AC motor using DTMF method; DTMF stands for dual tone multiple frequencies . The main idea of this project is to control the speed of an AC motor by wireless communication using DTMF decoder technique aiming at the fine use of mobile technology in our day to day use of automated products. Mobile phones have different frequencies for each number printed on it. These numbers when pressed during call duration produces a tone of certain frequency. This frequ...