logo
C#, 320 стр

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

Уже упоминалось о том, что при выполнении явных преобразований могут возникать нежелательные явления, например, потеря точности. Я говорил, что вся ответственность за это ложится на программиста, и легче ему от этого не становится. А какую часть этого бремени может взять на себя язык программирования? Что можно предусмотреть для обнаружения ситуаций, когда такие явления все-таки возникают? В языке 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", x);

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);

}

}

}

}