System.Exception and System.ApplicationException
There remains confusion over what to inherit from when creating custom exceptions. Best-practises opinions range from the .NET Framework documentation: “If you are designing an application that needs to create its own exceptions, derive from the ApplicationException class,” through to the .NET Framework Standard Library Annotated Reference (Vol.1): “You should not define new exception classes derived from ApplicationException; use Exception instead. In addition, you should not write code that catches ApplicationException.” So which is it?
System.Exception
If extending the base exception class with additional members, inherit from System.Exception. The name of such inherited classes should end with “Exception.”
Properly, System.Exception should have been declared as abstract with a recommendation to be inherited only by concrete exception classes. Doing so would have avoided the question of which to use right from the start, and would have also helped MS with versioning. However, since things are what they are, in this situation it makes sense to inherit and extend System.Exception. The rule to tend towards a flat hierarchy wins. Inherit from System.Exception when creating a class which adds members.
System.ApplicationException
Applications often provide their own custom exception types (e.g. CmsException, SharePointException) which do not add properties or methods, but simply subclass System.ApplicationException with a new name. If more detailed expections are required for the application, they will then inherit from this base class. This makes it convenient to throw application-specific exceptions that can be identified distinctly inside a try-catch block. When doing the same for your own applications, inherit from System.ApplicationException.
For both System.Exception and System.Application, the rules are consistent in this way: they work with the Framework as it is, not as we would like it to be. Since ApplicationException exists and is in common use, it would be a deviation to derive application-specific exceptions directly from System.Exception. So while you still won't catch ApplicationException directly, you should certainly catch its descendants.
System.SystemException
The difference between ApplicationException and SystemException is that SystemExceptions are thrown by the CLR, and ApplicationExceptions are thrown by Applications. For example, SqlException inherits from SystemException. Included here to make this list complete, there should not be any circumstances where one would need to inherit from SystemException.
These rules are a dump of the model as it exists in my head after a few months of picking up bits and pieces from the various sources. It isn't gospel, but it works for me. Always subject to improvement, feel free to comment.
Further references:
DotNetJunkies article which covers some of this: .NET Anatomy - Structured Exception Handling in .NET
How to Rethrow an Exception Correctly
Design Guidelines Update: Exception Message Guidelines
Exception Management Application Block
Rich Custom Error Handling