Why must a type thrown or caught derive from System.Exception

It is an arbitrary choice of the designers of the CLS. Presumably they made this choice for reasons of consistency. C# follows the CLS; the requirement is enforced by the compiler for this reason, not for any technical reason related to the implementation of the Exception type.

The CLI can actually throw any object. See http://jilc.sourceforge.net/ecma_p3_cil.shtml#_Toc524462405.


Design Guidelines for Exceptions

Exceptions are the standard mechanism for reporting errors. Applications and libraries should not use return codes to communicate errors. The use of exceptions adds to a consistent framework design and allows error reporting from members, such as constructors, that cannot have a return type

throw (C# Reference)

The thrown exception is an object whose class is derived from System.Exception, as shown in the following example.

class MyException : System.Exception {}
// ...
throw new MyException();

Exceptions Overview

In the .NET Framework, an exception is an object that inherits from the Exception Class

So, your exception must derive from System.Exception, but it's up to you, how you organize it within.


I think your premise is mistaken. It is possible that an object is thrown that is not derived from System.Exception. You just can't throw it in C# or examine the object in a catch clause. From section 8.10 of the C# spec (v4.0):

Some programming languages may support exceptions that are not representable as an object derived from System.Exception, although such exceptions could never be generated by C# code. A general catch clause may be used to catch such exceptions. Thus, a general catch clause is semantically different from one that specifies the type System.Exception, in that the former may also catch exceptions from other languages.

An example of a general catch:

try
{
}
catch (Exception) { } // 'specific' catch
catch { } // 'general' catch

In particular, this is important when calling unmanaged code.

Some types always seem to get special treatment in every language. Mostly because they are so fundamental to the system. System.Exception, System.ValueType, System.Delegate are all special types in C# that are tightly bound to language keywords and the CLR, so it is not surprising that you can't just implement classes that take over their roles.