Try-Catch-Finally in C#


This article has been excerpted from book "The Complete Visual C# Programmer's Guide" from the Authors of C# Corner.

If you are interested in executing a certain block of code irrespective of whether an exception occurs or not and still worry about catching an exception you might use the try-catch-finally block. Even if a goto statement is present in a try block, the control gets transferred to the label in the goto, only after executing the finally block. Listing 7.6 illustrates the structure of the finally block.

Listing 7.6: Try-Catch-Finally Syntax


        try
        {
            //Even if a goto statement were here
            //control gets transferred to the statement identified in
            //goto statement only after executing the finally block.
        }

        catch
        {
            //Catch the exception
        }

        finally
        {
            //this block of code will always get executed whether an
            // exception occurs or not as long as there are no exceptions
            // within this block itself. If an Exception is thrown here
            // some outer try block should handle it
            //Any Clean up code goes here. Especially to release any
            //system resources such as file handles and network
            //connections
        }


Let's go through an example so that we can better understand the purpose of the finally block. Listing 7.7 illustrates the use of the finally block to clean up file states.

Listing 7.7: Exception7.cs, TestFinally


namespace
TestFinally
{
    using System;
    using System.IO;
    /// <summary>
    /// Summary description for TestFinally.
    /// </summary>

    public class TestFinally
    {
        public TestFinally()
        {
                      // TODO: Add Constructor Logic here
        }

        public static void Main()
        {
            StreamReader sr1 = null;
            StreamWriter sw1 = null;

            try
            {
                System.Console.WriteLine("In try block");

                //Open files
                sr1 = new StreamReader(File.Open("Test1.txt",
                System.IO.FileMode.Open));
                sw1 = new StreamWriter(File.Open("Test2.txt",
                System.IO.FileMode.Append,
                FileAccess.Write));

                while (sr1.Peek() != -1)
                {
                    sw1.WriteLine(sr1.ReadLine());
                }

                goto MyLabel;
            }
            catch (Exception e)
            {
                Console.WriteLine(String.Concat(e.Message,
                e.StackTrace));
            }

            finally
            {
                //Int32 j ;
                //j=0;
                //j=j/5;
                //If an Exception is thrown here some outer
                //try block should handle it. The finally block
                // will not be completely executed
                Console.WriteLine("In finally block");
                //we need to make sure that Close method of the
                //Streamreader sr1 or StreamWriter sw1
                //is called irrespective of whether an exception
                // occurs or not
                //to release any system resources associated with
                //the reader or writer

                if (sr1 != null)
                {
                    sr1.Close();
                }

                if (sw1 != null)
                {
                    sw1.Close();
                }
            }

        MyLabel:
            Console.WriteLine("In Mylabel");
            // note: the following statements are not allowed
            //inside a finally block:
            //return, goto, break and continue

 
            Console.ReadLine();
        }
    }
}


In Listing 7.7, inside the Main method, we opened two files. First we opened Test1.txt using a StreamReader object by passing a FileStream object returned by the File.Open method, and then we opened Test2.txt through a StreamWriter object by passing a FileStream object returned by the File.Open method. The intention here is to copy lines of Test1.txt and append them to Test2.txt. If the code in the try block executes successfully, we want to close StreamReader sr1 and StreamWriter sw1 so that system resources associated with the reader/writer are released.

If Test1.txt opens successfully but for some reason there is an exception thrown while opening Test2.txt, we still want to close the stream associated with Test1.txt. So in this example we have added the close methods in the finally code block so that they can be positively executed. We are checking for a null value because if none of the files is opened, we would get a nulldereferencing exception in the finally block.

We have also added a goto statement and a label to show that the label is executed only after executing the finally block.

If one of the two files is not opened successfully, the output would look like figure 7.3. The exceptions are written out to the console from the catch block and the finally block is entered to clean up the files.

fig7.3.gif

Figure 7.3: Output of Listing 7.7

If the two files are opened successfully, the output would look like figure 7.4Note that the finally block is entered regardless of whether or not an exception is thrown and the files are closed.

The only time a finally block will not get executed completely is if an exception occurs in the finally block.

Note: goto, break, continue, and return statements inside a finally block clause cause an error.

Conclusion

Hope this article would have helped you in understanding Try-Catch-Finally in C#. See other articles on the website on .NET and C#.

visual C-sharp.jpg The Complete Visual C# Programmer's Guide covers most of the major components that make up C# and the .net environment. The book is geared toward the intermediate programmer, but contains enough material to satisfy the advanced developer.

Up Next
    Ebook Download
    View all
    Learn
    View all