Shiman’s Weblog

Collecting stones from the sea-shore.

C# .NET System.Exception Properties

System.Exception has a full complement of attributes providing information on the exception. The following table describes the properties of the Exception class.

Table: Exception Properties

Property

Description

Type

Read/Write

Data

Returns a dictionary collection that provides optional user-defined details of exception.

IDictionary

R

HelpLink

Link to a help file for the exception.

string

R/W

HResult

The HRESULT, which is a 32-bit error code common to COM, assigned to the exception. This is a protected property.

int

R/W

InnerException

When exceptions are propagated, the inner exception represents the previous exception.

Exception

R

Message

User-friendly message describing the exception.

string

R

Source

Name of application or object where exception occurred.

string

R/W

StackTrace

String representation of the call stack when the exception occurred.

string

R

TargetSite

Reference to the method where exception is raised.

MethodBase

R

The Message and InnerException properties are settable in constructors of the Exception class.

The following code uses some of the properties of the Exception class. In Main, MethodA is called, and an exception is raised. The exception is caught and handled in Main. In the catch block, the exception flag is set to false. Leveraging the TargetSite property, MethodA is then called again successfully. The TargetSite property returns a MethodBase type, which can be used to late bind and invoke a method.

using System;
using System.Reflection;

namespace Example.Exceptions
{
    public class Starter
    {
        public static bool bException = true;
        public static void Main()
        {
            try
            {
                MethodA();
            }
            catch (Exception except)
            {
                Console.WriteLine(except.Message);
                bException = false;
                except.TargetSite.Invoke(null, null);
                Console.ReadKey();
            }
        }

        public static void MethodA()
        {
            if (bException)
            {
                throw new ApplicationException("exception message");
            }
        }
    }
}

October 28, 2008 Posted by shiman | C#.Net, Computer Science, OOP, Programming | , , , , , , , , , | No Comments Yet

C# .NET System.Exception Functions

System.Exception has four constructors:

  • public Exception1()
  • public Exception2(string message)
  • public Exception3(string message, Exception innerException)
  • protected Exception4(Serialization info, StreamingContext context)

Exception1 is the default constructor. Exception2 constructor sets the user-friendly message of the exception. Exception3 constructor also sets the inner exception, which is the originating exception. Exception4 deserializes an exception raised remotely.

The Exception class has several other helpful functions. The table lists the important methods of the class.

Table: Exception Methods

Method Name

Result

GetBaseException

Returns the root exception in a chain of exception objects

GetObjectData

Serializes data of the Exception class

GetType

Returns the type of the exception

ToString

Concatenates the name of the exception object with the user-friendly message

The following code calls GetBaseException and outputs the error message of the initial exception. If the current exception is the first exception in a chain of exceptions, GetBaseException returns null. Alternatively, you can walk InnerException properties back to the first exception.

using System;

namespace Example.Exceptions
{
    public class Program
    {
        public static void Main()
        {
            try
            {
                MethodA();
            }
            catch (Exception except)
            {
                Exception original = except.GetBaseException();
                Console.WriteLine(original.Message);
            }

            Console.ReadKey();
        }

        public static void MethodA()
        {
            try
            {
                MethodB();
            }
            catch (Exception except)
            {
                throw new ApplicationException("Inner Exception", except);
            }
        }

        public static void MethodB()
        {
            throw new ApplicationException("Innermost Exception");
        }
    }
}

October 16, 2008 Posted by shiman | C#.Net, Computer Science, OOP, Programming | , , , , , , , , , | No Comments Yet

C# .NET Exceptions : Propagating Exceptions

Exceptions are not always handled locally where the exception is caught. It is sometimes beneficial to catch an exception and then propagate the exception. Propagating an exception is catching and then rethrowing the exception. Rethrowing an exception continues the search along the call stack to find an appropriate handler. Here are some reasons to propagate an exception:

  • There is a centralized handler for the exception. There are several reasons for implementing centralized handlers, including code reuse. Instead of handling an exception in various locations in an application, concentrate code for certain exceptions in a centralized handler. Wherever the exception is raised, the proper response is to record the exception and then delegate to the centralized handler. A central handler can be used to handle all exceptions in a single place.
  • Resources required to handle the exception are not available locally. For example, an exception is raised because of an invalid database connection. However, the correct connection string is read from a file not available where the exception occurs. The solution is to propagate the exception to a handler that has access to the file resource.
  • Propagate unwanted exceptions caught in the umbrella of the exception filter. This would be useful for catching all DataException types with the exception of the DuplicateNameException. One solution would be to write 12 individual catches—one for each of the data exceptions except for the DuplicateNameException exception. A better solution is to catch the DataException type and propagate the DuplicateNameException when necessary. This is one catch statement versus 12 catch statements and eliminates redundant code.
  • Catch an exception to gather information or to report on an exception, and then propagate the exception.

To propagate an exception, rethrow the same exception or another exception in the catch block. An empty throw statement propagates the caught exception. Alternatively, throw a different exception.

Exceptions might propagate through several layers of an application. Ultimately, the exception could percolate to the user interface level. As an exception percolates, the exception becomes less specific. Exceptions from the lower echelon of an application contain detailed information appropriate to the application developer, but probably not relevant to the user. Internal exceptions might contain security and other sensitive information not appropriate for a benign (or malicious) user. Record the facts of the internal exception if logging is preferable. Exceptions that reach the user should present user-relevant information: a user-friendly message, steps to resolve the exception, or even a customer support link.

When an original exception is rethrown, you can preserve the that exception in the InnerException attribute. Successive InnerException attributes form a chain of exceptions from the current exception to the original exception. The InnerException can be initialized in the constructor of the new exception. Here is sample code that propagates an exception and sets the inner exception:

using System;

namespace Examples.Exceptions
{
    public class Program
    {
        public static void Main()
        {
            try
            {
                MethodA();
            }
            catch (Exception except)
            {
                Console.WriteLine(except.Message);
            }
        }

        public static void MethodA()
        {
            try
            {
                MethodB();
            }
            catch (DivideByZeroException inner)
            {

                // record divide by zero exception in event log.

                // except is inner exception
                throw new Exception("Math exception", inner);
            }
        }

        public static void MethodB()
        {
            int var1 = 5, var2 = 0;
            var1 /= var2;
        }
    }
}

October 7, 2008 Posted by shiman | C#.Net, Computer Science, OOP, Programming | , , , , , , , , , | No Comments Yet

C# .NET Events : Raising (Custom) Events

At the discretion of a publisher, an event is raised and the methods of the subscribers are called back. Raise an event with the call operator “()”. Adding the call operator to the event raises the event. Because a delegate underlies an event, the Invoke method inherited from a multicast delegate is another means to raising an event. The signature of both the call operator and the Invoke method match the delegate of the event. Any parameters are passed to the called methods of the subscribers. If an event returns a value as defined by the event delegate, the function of the last subscriber sets the return. Do not raise an event for events without subscribers. Events with no subscribers are null, which can be tested. An application that raises an event that has no subscribers will incur an exception because of a null reference. This is the proper way to raise an event:

public void SomeMethod()
{
    if (anEvent != null)
    {
        anEvent(null, null);
    }
}

EventArgs

Events sometime provide subscribers with custom information pertaining to the event. The mouse click event provides the x and y coordinates of the mouse pointer in the MouseEventArgs class. The DataRowChangeEventArgs class provides the affected row and action of several database-related events, such as the RowChanged event. The PaintEventArgs class is instantiated in a paint event. It gives developers the clip rectangle and graphics object for the paint event. Custom information about an event is defined in an EventArgs derived class. MouseEventArgs, DataRowChangeEventArgs, PaintEventArgs, and other related classes derive from the EventArgs class. These classes represent the state information for the event.

The EventArgs derived class that contains the state information of the event is typically passed as the second parameter of the event. State information can also be specified in the other parameters of events.

This is code for a bank account. The NSF event is raised when the account is overdrawn. The BankEventArgs class provides the bank account balance and amount of the transaction that would overdraw the account.

using System;

namespace Examples.Events
{

    public class Program
    {
        public static void Main()
        {
            Bank account = new Bank();
            account.NSF += NSFHandler;
            account.Deposit(500);
            account.Withdrawal(750);
        }

        public static void NSFHandler(object o,
                BankEventArgs e)
        {
            Console.WriteLine("NSF Transaction");
            Console.WriteLine("Balance: {0}", e.Balance);
            Console.WriteLine("Transaction: {0}", e.Transaction);
        }

    }

    public delegate void OverDrawn(object o, BankEventArgs e);

    public class Bank
    {
        public event OverDrawn NSF; // non sufficient funds

        public decimal Deposit(decimal amountDeposit)
        {
            propBalance += amountDeposit;

            return propBalance;
        }

        public decimal Withdrawal(decimal amountWithdrawn)
        {
            decimal newBalance = propBalance - amountWithdrawn;
            if (newBalance < 0)
            {
                if (NSF != null)
                {
                    BankEventArgs args = new BankEventArgs(Balance, amountWithdrawn);
                    NSF(this, args);
                }

                return propBalance;
            }

            return propBalance = newBalance;
        }
        private decimal propBalance = 0;
        public decimal Balance
        {
            get
            {
                return propBalance;
            }
        }

    }

    public class BankEventArgs : EventArgs
    {

        public BankEventArgs(decimal amountBalance,
                decimal amountTransaction)
        {
            propBalance = amountBalance;
            propTransaction = amountTransaction;
        }

        private decimal propBalance;
        public decimal Balance
        {
            get
            {
                return propBalance;
            }
        }

        private decimal propTransaction;
        public decimal Transaction
        {
            get
            {
                return propTransaction;
            }
        }
    }
}

October 5, 2008 Posted by shiman | C#.Net, Computer Science, OOP, Programming | , , , , , , , , , | No Comments Yet