Основы программирования на C#


Проверяемые преобразования


Уже упоминалось о том, что при выполнении явных преобразований могут возникать нежелательные явления, например, потеря точности. Я говорил, что вся ответственность за это ложится на программиста, и легче ему от этого не становится. А какую часть этого бремени может взять на себя язык программирования? Что можно предусмотреть для обнаружения ситуаций, когда такие явления все-таки возникают? В языке C# имеются необходимые для этого средства.

Язык C# позволяет создать проверяемый блок, в котором будет осуществляться проверка результата вычисления арифметических выражений. Если результат вычисления значения источника выходит за диапазон возможных значений целевой переменной, то возникнет исключение (говорят также: "будет выброшено исключение") соответствующего типа. Если предусмотрена обработка исключения, то дальнейшее зависит от обработчика исключения. В лучшем случае, программа сможет продолжить корректное выполнение. В худшем, - она остановится и выдаст информацию об ошибке. Заметьте, не произойдет самого опасного - продолжения работы программы с неверными данными.

Синтаксически проверяемый блок предваряется ключевым словом checked. В теле такого блока арифметические преобразования проверяются на допустимость. Естественно, подобная проверка требует дополнительных временных затрат. Если группа операторов в теле такого блока нам кажется безопасной, то их можно выделить в непроверяемый блок, используя ключевое слово unchecked. Замечу еще, что и в непроверяемом блоке при работе методов Convert все опасные преобразования проверяются и приводят к выбрасыванию исключений. Приведу пример, демонстрирующий все описанные ситуации:

/// <summary> /// Демонстрация проверяемых и непроверяемых преобразований. /// Опасные проверяемые преобразования приводят к исключениям. /// Опасные непроверяемые преобразования приводят к неверным /// результатам, что совсем плохо. /// </summary> public void CheckUncheckTest() { x = -25^2; WhoIsWho ("x", x); b= 255; WhoIsWho("b",b); // Проверяемые опасные преобразования. // Возникают исключения, перехватываемые catch-блоком. checked { try { b += 1; } catch (Exception e) { Console.WriteLine("Переполнение при вычислении b"); Console.WriteLine(e); } try { b = (byte)x; } catch (Exception e) { Console.WriteLine("Переполнение при преобразовании к byte"); Console.WriteLine(e); } // непроверяемые опасные преобразования unchecked { try { b +=1; WhoIsWho ("b", b); b = (byte)x; WhoIsWho ("b", b); ux= (uint)x; WhoIsWho ("ux", ux); Console.WriteLine("Исключений нет, но результаты не верны!"); } catch (Exception e) { Console.WriteLine("Этот текст не должен появляться"); Console.WriteLine(e); } // автоматическая проверка преобразований в Convert // исключения возникают, несмотря на unchecked try { b = Convert.ToByte(x); } catch (Exception e) { Console.WriteLine("Переполнение при преобразовании к byte!"); Console.WriteLine(e); } try { ux= Convert.ToUInt32(x); } catch (Exception e) { Console.WriteLine("Потеря знака при преобразовании к uint!"); Console.WriteLine(e); } } } }



Содержание раздела