If you just use the generic Exception you will never be able to trap specific exceptions that are custom to your application. If you just use
try
{
}
catch (Exception ex)
{
}
You will catch every exception without being able to filter for specific errors.
Another reason I create a custom exception is to handle application specific exceptions that may occur for many reasons. This allows mean to throw an custom exception but customize the message associated with the exception. It also gives me another level of error handling that is for my specific application.
For example I have an enigineering application that sizes belt drive systems. The dll is also available for other people to use. I have an application exception that is thrown when an error occurs in the selection. The reason for the error can be for many reasons (invalid drive speed, incorrect horsepower requirements, etc.). Since there are many reasons for failure, a custom application exception allows me to give specific details for the failure.
This also allows me to document to users that method calls will throw application specific exceptions that they need to handle.
If your inheritting Exception class make sure to implement the constructors in the the base class that have a message, message + inner exception and serialized exception.
Here is an example I have.
/// <summary>
/// Drive error exception class. Thrown when a drive selection error has occured.
/// </summary>
[Serializable]
public class DriveException : ApplicationException
{
/// <summary>
/// Default constructor.
/// </summary>
public DriveException()
{
}
/// <summary>
/// Constructor used with a message.
/// </summary>
/// <param name="message">String message of exception.</param>
public DriveException(string message)
: base(message)
{
}
/// <summary>
/// Constructor used with a message and an inner exception.
/// </summary>
/// <param name="message">String message of exception.</param>
/// <param name="inner">Reference to inner exception.</param>
public DriveException(string message, Exception inner)
: base(message, inner)
{
}
/// <summary>
/// Constructor used in serializing the data.
/// </summary>
/// <param name="info">Data stored to serialize/de-serialize</param>
/// <param name="context">Defines the source/destinantion of the straeam.</param>
public DriveException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}