2015-05-07 8 views
8

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

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

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

+0

Запрет на голосование без объяснения причин должен быть запрещен – MatteoSp

+4

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

+0

Так получается, это не так очевидно, не так ли? – MatteoSp

ответ

5

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, который поддерживает поле типа объекта , который ссылается на исходное исключение. Это позволяет записывать трассировку стека. Когда он распространяется вверх по стеку:

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

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

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

В C#, в первой пули выше, и во втором случае второй пули, единственный способ, чтобы поймать исключение без ЦБС является использование без параметров улова блок.

2

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

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

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

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