Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the CLS mandates the throwing/catching of Exception derived objects?

Tags:

c++

c#

.net

clr

cls

The CLS is more restrictive than the CLR, which would allow you to throw and catch any type of objects (even value types). Why?

Also what would happen if some non CLS-compliant code threw a non Exception derived object while called by a CLS compliant code?

UPDATE Second question answered by @Marton. Still wonder why.

like image 273
MatteoSp Avatar asked May 07 '15 15:05

MatteoSp


2 Answers

CLS specifies a minimum set of language features needed by many applications in such a way that if an API uses only those features, it can be consumed by any CLS-compliant language. So naturally it is more restrictive than the CLR. On the other hand, the CLR is deigned to handle manged code from any CLI-compliant language.

An example of a language that allows throwing non-CLS-compliant exceptions (those not derived from System.Exception) is C++/CLI. This language was designed to be a superset of plain C++ which includes the ability to throw exceptions of any type. This could be the only good reason to throw non-CLS exceptions.

Regarding the second question. A non-CLS exception, when thrown, different things happen in different cases:

  • If CLR 1.X is managing the execution of the code, the exception propagates as is. In languages that only support CLS exceptions (C#), the exception can only be caught by a parameterless catch block. There is no easy way to access the exception and a stack trace will not be recorded.
  • On CLR 2.0 and later, the CLR internally always wraps the exception into a System.Runtime.CompilerServices.RuntimeWrappedException which maintains a field of type Object that references the original exception. This allows a stack trace to be recorded. When it propagates up the stack:

    1. If the System.Runtime.CompilerServices.RuntimeCompatibilityAttribute attribute was applied on the assembly of the function in which the CLR is looking for a matching catch block and WrapNonExceptionThrows set to true (automatically applied by the Visual C# and Basic compilers), then the exception continues to be wrapped.

    2. Otherwise, if the attribute was not applied or if WrapNonExceptionThrows was set to false, the exception is unwrapped every time a catch block is examined for matching.

Edit

In C#, in the first bullet above and the second case of the second bullet, the only way to catch a non-CLS exception is by using a parameterless catch block.

like image 55
Hadi Brais Avatar answered Sep 18 '22 14:09

Hadi Brais


The why part I cannot answer, but the second part I can:

what would happen if some non CLS-compliant code threw a non Exception derived object while called by a CLS compliant code?

If you throw a non-Exception-derived object, it will still be caught by CLS-compliant code, since it will be wrapped into a RuntimeWrappedException.

(The source article is worth a read for more details.)

like image 23
molnarm Avatar answered Sep 22 '22 14:09

molnarm