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

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

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

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

8

Решение

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

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

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

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

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

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

редактировать

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

5

Другие решения

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

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

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

(The исходная статья стоит прочитать для более подробной информации.)

2

По вопросам рекламы [email protected]