It seems that I've started a bit of an Exception sublcassing battle. Depending on the Microsoft Best Practices guide you follow...you can either inherit from System.Exception or System.ApplicationException. There's a good (but old) blog post that tries to clear up the confusion. I'll keep my example with Exception for now, but you can read the post and chose based on what you need:
There is a battle no more! Thanks to Frederik for pointing out FxCop rule CA1058 which states that your Exceptions should inherit from System.Exception rather than System.ApplicationException:
So, ideally, your custom Exception should look at least like this:
[Serializable]
public class MyException : Exception
{
public MyException ()
{}
public MyException (string message)
: base(message)
{}
public MyException (string message, Exception innerException)
: base (message, innerException)
{}
}
About the fact whether you should inherit from Exception or ApplicationException:
FxCop has a rule which says you should avoid inheriting from ApplicationException:
CA1058 : Microsoft.Design :
Change
the base type of 'MyException' so that
it no longer extends
'ApplicationException'. This base
exception type does not provide any
additional value for framework
classes. Extend 'System.Exception' or
an existing unsealed exception type
instead. Do not create a new exception
base type unless there is specific
value in enabling the creation of a
catch handler for an entire class of
exceptions.
Define a class that inherits from Exception. If necessary, define any unique members needed by your class to provide additional information about the exception. For example, the ArgumentException class includes a ParamName property that specifies the name of the parameter whose argument caused the exception, and the RegexMatchTimeoutException property includes a MatchTimeout property that indicates the time-out interval.
If necessary, override any inherited members whose functionality you want to change or modify. Note that most existing derived classes of Exception do not override the behavior of inherited members.
Determine whether your custom exception object is serializable. Serialization enables you to save information about the exception and permits exception information to be shared by a server and a client proxy in a remoting context. To make the exception object serializable, mark it with the SerializableAttribute attribute.
Define the constructors of your exception class. Typically, exception classes have one or more of the following constructors:
Exception(), which uses default values to initialize the properties of a new exception object.
Exception(String), which initializes a new exception object with a specified error message.
Exception(String, Exception), which initializes a new exception object with a specified error message and inner exception.
Exception(SerializationInfo, StreamingContext), which is a protected constructor that initializes a new exception object from serialized data. You should implement this constructor if you've chosen to make your exception object serializable.
Example:
using System;
using System.Runtime.Serialization;
[Serializable()]
public class NotPrimeException : Exception
{
private int _notAPrime;
public int NotAPrime { get { return _notAPrime; } }
protected NotPrimeException() : base()
{ }
public NotPrimeException(int value) : base(String.Format("{0} is not a prime number.", value))
{
_notAPrime = value;
}
public NotPrimeException(int value, string message) : base(message)
{
_notAPrime = value;
}
public NotPrimeException(int value, string message, Exception innerException) : base(message, innerException)
{
_notAPrime = value;
}
protected NotPrimeException(SerializationInfo info, StreamingContext context) : base(info, context)
{ }
}
Usage in throw:
throw new NotPrimeException(prime, "This is not a prime number."));
Usage in try/catch:
try
{
...
}
catch (NotPrimeException e)
{
Console.WriteLine( "{0} is not prime", e.NotAPrime );
}
To create your own exception, you can go with this example:
[Serializable()]
public class InvalidExampleException : System.Exception
{
public InvalidExampleException() : base() { }
public InvalidExampleException(string message) : base(message) { }
public InvalidExampleException(string message, System.Exception inner) : base(message, inner) { }
protected InvalidExampleException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
As said in Microsoft Docs, an exception in c# needs at least those four constructors.
Then, to use this exception in your code, you just have to do:
using InvalidExampleException;
public class test
{
public int i = 0;
public void check_i()
{
if (i == 0) // if i = 0: error
{
// exception
throw new InvalidExampleException("Index is zero");
}
}
}