The Dangers Of Exception Based Logic Part 2 – Filesystem Interaction


I have often time seen filesystem interaction code that heavily depends on exception handling.  Code out in the wild rarely exposes this problem in such a trivial way as my example code below, but just wanted to give another example.

 

 

Exception Based Logic: 14-21ms
Preemptive Error Checking Based Logic: 0ms

 

static void Main(string[] args)
{
    using (new QuickTimer("Exception Based Logic"))
    {
        for (int i = 0; i < 10; i++)
        {
            try
            {
                string userInputPath = @"C:\not\a\real\path\foo\bar.txt";
                File.WriteAllText(userInputPath, "Some String To Write");
            } catch (Exception ex)
            {
                Console.WriteLine("Error");
            }
        }
    }

    using (new QuickTimer("Preemptive Error Checking Based Logic"))
    {
        for (int i = 0; i < 10; i++)
        {
            string userInputPath = @"C:\not\a\real\path\foo\bar.txt";

            if (!File.Exists(userInputPath))
            {
                Console.WriteLine("Error");
                continue;
            }

            File.WriteAllText(userInputPath, "Some String To Write");
        }
    }
}

Comments (5)

  1. What about putting the loop within the try block?

    What time does that give?

  2. MSDN Archive says:

    I can’t put the loop inside the try block, because once File.WriteAllText is executed for the first time an exception of DirectoryNotFoundException will be thrown and it will be outside the loop.

    I am mostly just using the loop to show how this problem can scale.  If in our real code the loop was not needed, there was would be a very tiny speed difference.  Though if that piece of code is executed a lot and the program is half a million lines of code; chances are if it happens one place then it happened many places.

  3. dskcheck says:

    Good to read the reality .. and most of the decisions are based on the logical thinking where we can use the TRY..CATCH..

    Secondly, can you share the code that you have written for QuickTimer Class. All these days am using the following code to get the time span for executing any code.

    Method 1)

               long lStart = DateTime.Now.TimeOfDay.Ticks;

               for (int intCnt = 0; intCnt < intLstVal; intCnt++)

               {

                   ExecuteSomeMethod(10);

               }

               long lEnd = DateTime.Now.TimeOfDay.Ticks;

               cs.WriteLine("Started at .. " + lStart.ToString() + " and ended at .. " + lEnd.ToString());

               long lTmDiff = lEnd – lStart;

               cs.WriteLine("The MilliSeconds at the end is .. " + (lTmDiff / 10000).ToString() + " MilliSeconds");

    Method 2) Using the TimeSpan

               TimeSpan tsStart = DateTime.Now.TimeOfDay;

               for (int intCnt = 0; intCnt < intLstVal; intCnt++)

               {

                   cs.Write(intCnt.ToString() + "-");

                   DoObjectTest(10);

               }

               double dMs = DateTime.Now.TimeOfDay.Subtract(tsStart).TotalMilliseconds;

               cs.WriteLine("The time in MilliSeconds to execute the code block is .. " + dMs.ToString() + " MilliSeconds");

    Please comment or suggest any new methods to have more accurate time details.

    Thanks for reading.

  4. Timothy Fries says:

    In a real-world situation you would still need a try/catch block within the loop in the second test to account for the possibility of a race condition where the filesystem changes between your preemptive check and the actual write.

  5. MSDN Archive says:

    @dskcheck

    I just use http://jcheng.wordpress.com/2007/10/23/code-sample-quicktimer-2/

    @Timothy

    You are right.  There are still tons of cases where we need to have try/catch for things way out of our control.  But it doesn’t mean we have to depend on them for things that we could figure out faster on our own.

Skip to main content