Wednesday, July 11, 2007

Error Handling

Shows a good way to handle exceptions; that is try to log it and then swallow it if it succeeds in logging it, but otherwise throw it up to the caller.

Please note that Logging is used as an example for the catch block processing just to demonstrate the concept; but it could equally apply to any call inside the catch block that can throw exceptions, for any emaling of errors which may also be done inside the catch block.

[C#]

// ----------------------------------------------
// From: http://coding-help.blogspot.com/
// Title: Error Handling
// Date: 12 July 2007
// Author: R. K. Wijayaratne
// Description: Shows a good way to handle
// exceptions; that is try to log it and then
// swallow it if it succeeds in logging it,
// but otherwise throw it up to the caller.
//
// Please note that Logging is used as an
// example for the catch block processing
// just to demonstrate the concept; but it
// could equally apply to any call inside the
// catch block that can throw exceptions,
// e.g. emailing of errors which may also
// be done inside the catch block.
//
// To Run: Create a new C# file, e.g. "Program.cs",
// copy and paste the code below into it and save.
// To compile it open the .NET Framework command
// prompt and type:
//
// csc C:\MyPath\Program.cs
//
// where "C:\MyPath\" is the path of the C# file.
// If there are any errors correct them. To run
// the program type "Program" and press "Enter."
// ----------------------------------------------

using System;
using System.Diagnostics;

public class TestHarness
{
  // Program entry point.
  static void Main(string[] args)
  {
    // Start running the test.
    StartTest();
  }

  // Test driver method.
  public static void StartTest()
  {
    try
    {
      // Test error handling.
      TestCase.TestErrorHandling();
    }
    catch (Exception exc)
    {
      // Write errors to console.
      Console.Write(exc.ToString());
    }
  }
}

public class TestCase
{
  public static void TestErrorHandling()
  {
    try
    {
      // Try to do some work.
      // Doing some work...
      // Simulate error.
      throw new InvalidOperationException();
    }
    catch (InvalidOperationException invOpExc)
    {
      string errDesc = "An invalid operation"
      + " occurred while doing some work.";
      string extraErrs = null;
      bool handled = true;

      try
      {
        // Try to log original error.
        EventLog.WriteEntry(
          "Program",
          errDesc+"\n\n"+invOpExc.ToString(),
          EventLogEntryType.Error);

        // Simulate new error during logging.
        throw new ArgumentException();
      }
      catch (ArgumentException argExc)
      {
        handled = false;
        extraErrs += "\n\nAdditional error"
        + " occurred while"
        + " logging:\n\n"
        + argExc.ToString();
      }

      // Throw it up to caller if not handled
      // and also append any logging errors.
      if (!handled)
      {
        // Append logging errors.
        errDesc = string.Format("{0}\n====="
          + "{1}\n\n=====\n",
          errDesc, extraErrs);

        throw new Exception(errDesc, invOpExc);
      }
      //else // Implicit.
      //{
        // Logging and other corrective
        // measures were successful
        // and the error was handled
        // so swallow the error.
      //}
    }
    finally // Optional.
    {
      // Always gets called so do any clean-up
      // here such closing database connections
      // and releasing other valuable resources.
    }
  }
}

Console Output

System.Exception: An invalid operation occurred while doing some work.
=====

Additional error occurred while logging:

System.ArgumentException: Value does not fall within the expected range.
at TestCase.TestErrorHandling()

=====
---> System.InvalidOperationException: Operation is not valid due to the current state of the object.
at TestCase.TestErrorHandling()
--- End of inner exception stack trace ---
at TestCase.TestErrorHandling()
at TestHarness.StartTest()


Also See

  1. See 'Exception' (on MSDN) here http://msdn2.microsoft.com/en-us/library/5b2yeyab.aspx

  2. See 'Catch Block Error Handling' here http://coding-help.blogspot.com/2007/07/catch-block-error-handling.html

Catch Block Error Handling

Shows a good way to handle errors that may occur inside the catch block, for example while logging the original error.

Please note that logging and emailing are used as examples for the catch block processing just for demonstrating the concept; but it could equally apply to any call inside the catch block that can throw exceptions.

[C#]

// ----------------------------------------------
// From: http://coding-help.blogspot.com/
// Title: Catch Block Error Handling
// Date: 11 July 2007
// Author: R. K. Wijayaratne
// Description: Shows a good way to handle errors
// that may occur inside the catch block, for
// example while logging the original error.
//
// Please note that Logging and emailing are used
// as examples for the catch block processing
// just for demonstrating the concept; but it
// could equally apply to any call inside the
// catch block that can throw exceptions.
//
// To Run: Create a new C# file, e.g. "Program.cs",
// copy and paste the code below into it and save.
// To compile it open the .NET Framework command
// prompt and type:
//
// csc C:\MyPath\Program.cs
//
// where "C:\MyPath\" is the path of the C# file.
// If there are any errors correct them. To run
// the program type "Program" and press "Enter."
// ----------------------------------------------

using System;

public class Tester
{
  // Program entry point.
  static void Main(string[] args)
  {
    // Start running the test.
    Tester.StartTest();
  }

  // Test driver method.
  public static void StartTest()
  {
    try
    {
      // Test error handling.
      TestHelper.TestErrorHandling();
    }
    catch (Exception exc)
    {
      // Write errors to console.
      Console.Write(exc.ToString());
    }
  }
}

public class TestHelper
{
  public static void TestErrorHandling()
  {
    try
    {
      // Try to do some work.
      // Doing some work...
      // Simulate error.
      throw new InvalidOperationException();
    }
    catch (InvalidOperationException invOpExc)
    {
      string errDesc = "An invalid operation"
      + " occurred while doing some work.";
      string extraErrs = null;
      bool handled = true;

      try
      {
        // Try to log original error.
        // Logging original error...
        // Simulate new error.
        throw new SystemException();
      }
      catch (SystemException sysExc)
      {
        handled = false;
        extraErrs += "\n\nAdditional error"
        + " occurred while"
        + " logging:\n\n"
        + sysExc.ToString();
      }

      try
      {
        // Try to email original error.
        // Emailing original error...
        // Simulate new error.
        throw new ArgumentException();
      }
      catch (ArgumentException argExc)
      {
        handled = false;
        extraErrs += "\n\nAdditional"
        + " error occurred"
        + " while emailing:\n\n"
        + argExc.ToString();
      }

      // Throw it up to caller if not handled.
      if (!handled)
      {
        errDesc = string.Format("{0}\n====="
              + "{1}\n\n=====\n",
              errDesc, extraErrs);

        throw new Exception(errDesc, invOpExc);
      }
    }
  }
}

Console Output

System.Exception: An invalid operation occurred while doing some work.
=====

Additional error occurred while logging:

System.SystemException: System error.
at TestHelper.TestErrorHandling()

Additional error occurred while emailing:

System.ArgumentException: Value does not fall within the expected range.
at TestHelper.TestErrorHandling()

=====
---> System.InvalidOperationException: Operation is not valid due to the current state of the object.
at TestHelper.TestErrorHandling()
--- End of inner exception stack trace ---
at TestHelper.TestErrorHandling()
at Tester.StartTest()


Also See

  1. See 'Exception' (on MSDN) here http://msdn2.microsoft.com/en-us/library/5b2yeyab.aspx

Passing Parameters

The int and the string default to being passed by value while the array and the object default to being passed by reference. I thought strings were reference types and arrays of chars!

If the below is modified by adding the "ref" key-word at the front of each argument and parameter; they all get passed by reference.

[C#]

// ----------------------------------------------
// From: http://coding-help.blogspot.com/
// Title: Passing Parameters
// Date: 11 July 2007
// Author: R. K. Wijayaratne
// Description: Tests how different types
// get passed as parameters.
//
// To Run: Create a new C# file, e.g. "Program.cs",
// copy and paste the code below into it and save.
// To compile it open the .NET Framework command
// prompt and type:
//
// csc C:\MyPath\Program.cs
//
// where "C:\MyPath\" is the path of the C# file.
// If there are any errors correct them. To run
// the program type "Program" and press "Enter."
// ----------------------------------------------

using System;

public class SomeObject
{
  public string ValueA;
  public int ValueB;
}

public class Tester
{
  // Program entry point.
  static void Main(string[] args)
  {
    // Start running the test.
    Tester.StartTest();
  }

  // Test driver method.
  public static void StartTest()
  {
    // Initialize values.
    int someInt = 1;
    string someString = "1";
    char[] charArr = new char[] { '1' };
    SomeObject someObj = new SomeObject();
    someObj.ValueA = "1";
    someObj.ValueB = 1;

    // Call to modify values.
    TestHelper.TestPassByRef(someInt,
    someString, charArr, someObj);

    // Output changes to console.
    Console.Write("someInt: {0}\nsomeString: {1}\n"
    + "charArr[0]: {2}\nsomeObj.ValueA: {3}\n"
    + "someObj.ValueB: {4}\n", someInt,
    someString, charArr[0], someObj.ValueA,
    someObj.ValueB);
  }
}

public class TestHelper
{
  public static void TestPassByRef(int someInt,
  string someString, char[] charArr,
  SomeObject someObj)
  {
    // Modify values.
    someInt = 2;
    someString = "2";
    charArr[0] = '2';
    someObj.ValueA = "2";
    someObj.ValueB = 2;
  }
}

Console Output

someInt: 1
someString: 1
charArr[0]: 2
someObj.ValueA: 2
someObj.ValueB: 2


Also See

  1. See 'C# Programmer's Reference: Passing Parameters' here http://msdn2.microsoft.com/en-us/library/0f66670z(vs.71).aspx

  2. See 'Parameter passing in C#' here http://www.yoda.arachsys.com/csharp/parameters.html

  3. See 'Parameter passing in C#' here http://rapidapplicationdevelopment.blogspot.com/2007/01/parameter-passing-in-c.html