CLR: если конструктор потерпит неудачу, он всегда будет выдавать исключение?
В Delphi, если во время создания объекта возникло исключение: любая выделенная память будет освобождена и будет сгенерировано исключение. Например, следующее гарантированно либо вернет действительный Camera
возразить или сгенерировать исключение:
Camera c = new Camera();
Вам никогда не приходилось проверять результирующую переменную на null:
Camera c = new Camera();
if (c == null)
throw new Exception("Error constructing Camera") //waste of time
То же самое в CLR?
И есть ли другие синтетические конструкции, в которых возвращаемое значение гарантированно либо будет действительным, либо выдает исключение?
- Создание структур (например, Rectangle)?
- получить член перечисления?
- результат Object.ToString()?
- математические операции?
В случае выполнения математики:
Int32 aspect = 1650.0 / 1080.0;
if (aspect == null)
throw new Exception("Division of two numbers returned null")
2 ответа
Конструктор в.Net гарантированно возвращает ненулевой экземпляр типа объекта. Является ли экземпляр допустимым, зависит от индивидуальной семантики типа.
Исключения, сгенерированные в конструкторе, не будут произвольно поглощены CLR (хотя пользовательский код может их проглотить). CLR будет распространять исключение точно так же, как исключения, генерируемые любым другим методом, и объекты в конечном итоге будут должным образом собираться мусором.
Что касается других случаев, которые вы упомянули
- Создание структур: структуры по определению не могут быть нулевыми. Исключения, сгенерированные в конструкторе, будут распространяться нормально
- Получение элемента перечисления. Перечисления являются типами strutures / value и не могут быть нулевыми.
- результат Object.ToString(): это может (и, к сожалению, будет) быть нулевым. String является ссылочным типом, и вполне допустимо возвращать null из переопределения ToString (пожалуйста, не делайте этого).
- Математические операции: это сильно зависит как от настройки переполнения вашего проекта, так и от конкретного используемого типа (целочисленная или с плавающей запятой).
Математический вопрос почти заслуживает ответа сам по себе. С одной стороны, результат математической операции над примитивными типами никогда не будет нулевым. Но это все еще может быть недействительным. Например, следующий код не будет выдан, но будет ли результат действительным, сильно зависит от вашего конкретного сценария
float f1 = 1.0;
float f2 = f1 / 0;
На данный момент f2 является очень специфическим значением с плавающей точкой, которое не представляет действительное число. Это действительно? Зависит от вашего варианта использования.
Да. Я хотел бы выразить это следующим образом (поскольку сбой может означать и логический сбой): если конструктор не выдает исключение, возвращаемое значение гарантированно не будетnull
поэтому вам никогда не придется выполнять такую проверку.
Создание структур (например, Rectangle): A struct
не может быть null
совсем (Nullable
типы считаются совершенно разными типами, т.е. typeof(int?) != typeof(int)
). Вызов конструктора для структуры либо завершится неудачей, вызвав исключение, либо вернет экземпляр.
Получение члена перечисления: An enum
это просто набор констант. Нет ничего лучше, чем "получить член во время выполнения". Он подставляется во время компиляции.
Результат Object.ToString()
Как и любой метод, он может вернуть любое допустимое значение для string
тип, который включает null
и может также вызвать исключение (в этом случае, оно не возвращает значение вообще).
Математические операции: все выражения возвращают значение или выдают исключение. Возвращаемое значение может быть любым допустимым значением для этого типа (например, Int32
никогда не может быть null
).