Почему CLS требует выдачи / перехвата объектов, производных от исключений?

CLS более строгий, чем CLR, что позволяет вам бросать и перехватывать объекты любого типа (даже типы значений). Почему?

Также что произойдет, если какой-то несовместимый с CLS код выбросит объект, не являющийся производным от исключения, при вызове кодом, совместимым с CLS?

ОБНОВЛЕНИЕ. На второй вопрос ответил @Marton. Все еще удивляюсь, почему.


person MatteoSp    schedule 07.05.2015    source источник
comment
голосование "против" без объяснения причин должно быть запрещено   -  person MatteoSp    schedule 07.05.2015
comment
Существует правило CLS, поэтому исключения, создаваемые кодом, написанным на одном языке, могут быть разумно пойманы кодом, написанным на другом. Спецификация CLI не исключает возможности того, что он может быть полезным на каком-то непонятном языке, чтобы бросить что-то еще. Наверняка вам будет сложно найти пример такого языка. То, что происходит, в некоторой степени очевидно: программа вылетает без возможности поймать или диагностировать исключение.   -  person Hans Passant    schedule 07.05.2015
comment
Получается, не все так очевидно, правда?   -  person MatteoSp    schedule 07.05.2015


Ответы (2)


CLS определяет минимальный набор языковых функций, необходимых многим приложениям, таким образом, что если API использует только эти функции, он может быть использован любым CLS-совместимым языком. Естественно, он более строгий, чем CLR. С другой стороны, среда CLR предназначена для обработки управляемого кода на любом языке, совместимом с CLI.

Примером языка, который позволяет генерировать исключения, не совместимые с CLS (не производные от System.Exception), является C ++ / CLI. Этот язык был разработан как надмножество простого C ++, который включает возможность генерировать исключения любого типа. Это может быть единственной веской причиной для создания исключений, отличных от CLS.

По поводу второго вопроса. При возникновении исключения, отличного от CLS, в разных случаях происходят разные вещи:

  • Если CLR 1.X управляет выполнением кода, исключение распространяется как есть. В языках, которые поддерживают только исключения CLS (C #), исключение может быть перехвачено только блоком catch без параметров. Нет простого способа получить доступ к исключению, и трассировка стека не будет записана.
  • В CLR 2.0 и более поздних версиях среда CLR всегда внутренне оборачивает исключение в System.Runtime.CompilerServices.RuntimeWrappedException, которое поддерживает поле типа Object, которое ссылается на исходное исключение. Это позволяет записывать трассировку стека. Когда он распространяется вверх по стеку:

    1. Если атрибут System.Runtime.CompilerServices.RuntimeCompatibilityAttribute был применен к сборке функции, в которой CLR ищет соответствующий блок catch, а для параметра WrapNonExceptionThrows установлено значение true (автоматически применяется компиляторами Visual C # и Basic), исключение продолжает упаковываться.

    2. В противном случае, если атрибут не применялся или если для параметра WrapNonExceptionThrows было установлено значение false, исключение разворачивается каждый раз, когда блок catch проверяется на соответствие.

Изменить

В C # в первом маркере выше и во втором случае второго маркера единственный способ поймать исключение, не относящееся к CLS, - это использовать блок catch без параметров.

person Hadi Brais    schedule 20.05.2015

На часть почему я не могу ответить, но на вторую часть я могу:

что произойдет, если какой-то несовместимый с CLS код выбросит объект, не являющийся производным от исключения, при вызове кодом, совместимым с CLS?

Если вы выберете объект, не являющийся производным от исключения, он все равно будет перехвачен CLS-совместимым кодом, поскольку он будет заключен в RuntimeWrappedException.

(Дополнительную информацию стоит прочитать в исходной статье.)

person molnarm    schedule 07.05.2015