Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Операция кастинга - приведения к типу






Уже говорилось, что правила вычисления выражения позволяют по его записи однозначно вычислить значение выражения и его тип при соблюдении естественных требований к его операндам. В ходе вычисления выражения может возникать необходимость выполнения преобразования типов операндов. По возможности эти преобразования выполняются автоматически, неявно для программиста. Но неявные преобразования ограничены, поскольку могут быть только безопасными. Когда же нужно выполнить опасное преобразование, программист должен задать его явно. Одна из возможностей явного задания преобразования типа состоит в применении операции приведения к типу, называемой также кастингом. Это унарная операция со следующим синтаксисом:

(T)x

Здесь в скобках указывается тип, к которому следует привести выражение x. Нужно понимать, что не всегда существует явное приведение типа источника к типу цели T. Операция кастинга применима только для приведения типов внутри арифметического типа. С ее помощью один арифметический подтип можно привести к другому подтипу, но нельзя, например, целочисленные типы привести к логическому типу bool.

Рассмотрим примеры приведения типа:

byte b1 = 1, b2 = 2, b3; //b3 = b1 + b2; b3 = (byte)(b1 + b2);

В этом примере необходимо сложить две переменные типа byte и, казалось бы, никакого приведения типов выполнять не нужно, результат будет также иметь тип byte, согласованный с левой частью оператора присваивания. Однако это не так по той простой причине, что отсутствует операция сложения над короткими числами. Реализация сложения начинается с типа int. Поэтому перед выполнением сложения оба операнда неявно преобразуются к типу int, результат сложения будет иметь тип int, и при попытке присвоить значение выражения переменной типа byte возникнет ошибка периода компиляции. По этой причине оператор во второй строке кода закомментирован. Программист вправе явно привести выражение к типу byte, что и демонстрирует третья строка кода, в которой использована операция приведения к типу.

В следующем фрагменте кода демонстрируется еще один пример приведения типа:

int tempFar, tempCels; tempCels = -40; tempFar = (int)(1.8 * tempCels) + 32;

Результат умножения имеет тип double по типу первого операнда. Перед тем как выполнять сложение, результат приводится к типу int. После приведения сложение будет выполняться над целыми числами, результат будет иметь тип int, и не потребуется никаких преобразований для присвоения полученного значения переменной tempFar. Если убрать приведение типа в этом операторе, то возникнет ошибка на этапе компиляции.

Рассмотрим еще один пример:

//if ((bool)1) b3 = 100; if (Convert.ToBoolean(1)) b3 = 100;

В этом примере показана попытка применить кастинг для приведения типа int к типу bool. Такое преобразование типа с помощью операции кастинга не разрешается и приводит к ошибке на этапе компиляции. Но, заметьте, это преобразование можно выполнить более мощными методами класса Convert.

Проверяемые и непроверяемые блоки и выражения

В C# реализован механизм проверки переполнения разрядной сетки и потери точности при выполнении арифметических операций (т.е. проверка корректности опасных преобразований). Он активируется в так называемых проверяемых блоках. Блок или выражение называется проверяемым (непроверяемым), если ему предшествует ключевое слово checked (unchecked). В проверяемых блоках контролируется вычисление арифметических операций и возникает исключительная ситуация, если, например, при вычислениях происходит переполнение разрядной сетки числа. В непроверяемых блоках такая исключительная ситуация будет проигнорирована, и вычисления продолжатся с неверным результатом.

Слегка модифицируем выше приведенный пример:

byte b1 = 100, b2 = 200, b3; //b3 = b1 + b2; b3 = (byte)(b1 + b2);

Если в предыдущем примере с байтами все вычисления были корректны, то теперь результат вычисления b3 просто не верен. При сложении был потерян старший разряд со значением 256, и b3 вместо 300 получит значение 44 из диапазона, допустимого для типа byte. Плохо, когда при выполнении программы возникает исключительная ситуация и программа не может далее нормально выполняться. Но еще хуже, когда программа завершает свою работу, выдавая неправильные результаты. Ложь хуже отказа. Кто виноват в возникшей ситуации? Программист, поскольку именно он разрешил опасную операцию, не позаботился о ее контроле и обработке исключительной ситуации в случае ее возникновения. Программист должен знать, что по умолчанию вычисления выполняются в режиме unchecked. А потому, если нет полной уверенности в возможности проведения преобразования, запись опасных преобразований должна сопровождаться введением проверяемых выражений, охраняемых блоков и сопровождающих их обработчиков исключительных ситуаций.

byte var1 = 250; byte var2 = 150; try { byte sum = checked((byte)(var1+var2)); Console.WriteLine(" Сумма: {0}", sum); } catch (OverflowException ex) { Console.WriteLine(ex.Message); Console.ReadLine();

}

Если создается приложение, в котором переполнение никогда не должно проходить незаметно, может выясниться, что обрамлять ключевым словом checked приходится раздражающе много строк кода. На такой случай в качестве альтернативного варианта в компиляторе С# поддерживается флаг /checked. При активизации этого флага проверке на предмет возможного переполнения будут автоматически подвергаться все имеющиеся в коде арифметические операции, без применения для каждой из них ключевого слова checked. Обнаружение переполнения точно так же приводит к генерации соответствующего исключения во время выполнения.

Для активизации этого флага в Visual Studio 2010 необходимо открыть страницу свойств проекта, перейти на вкладку Build (Построение), щелкнуть на кнопке Advanced (Дополнительно) и в открывшемся диалоговом окне отметить флажок Check for arithmetic overflow/underflow (Проверять арифметические переполнения и потери точности).

Важно отметить, что в С# предусмотрено ключевое слово unchecked, которое позволяет отключить выдачу связанного с переполнением исключения в отдельных случаях.

Преобразование в строковый тип

Преобразования в строковый тип всегда определены, поскольку все типы являются потомками базового класса object и наследуют метод ToString (). Конечно, родительская реализация этого метода чаще всего не устраивает наследников. Поэтому при определении нового класса в нем должным образом переопределяется метод ToString. Для встроенных типов определена подходящая реализация этого метода. В частности, для всех подтипов арифметического типа метод ToString() возвращает строку, задающую соответствующее значение арифметического типа. Заметьте, метод ToString следует вызывать явно. В ряде ситуаций вызов метода может быть опущен, и он будет вызываться автоматически. Его, например, можно опускать при сложении числа и строки. Если один из операндов операции " +" является строкой, то операция воспринимается как конкатенация строк и второй операнд неявно преобразуется к этому типу. Вот соответствующий пример:

/// < summary> /// Демонстрация преобразования в строку/// данных различного типа./// < /summary> public void ToStringTest(){ string name; uint age; double salary; name = " Владимир Петров"; age = 27; salary = 27000; string s = " Имя: " + name + ". Возраст: " + age.ToString() + ". Зарплата: " + salary; Console.WriteLine(s); }

Здесь для переменной age метод был вызван явно, а для переменной salary он вызывается автоматически.

Пример int + string.

Преобразования строкового типа в другие типы

Хотя неявных преобразований строкового типа в другие типы нет, необходимость в преобразованиях существует. Когда пользователь вводит данные различных типов, он задает эти данные как строки текста, поскольку текстовое представление наиболее естественно для человека. Поэтому при вводе практически всегда возникает задача преобразования данных, заданных текстом, в " настоящий" тип данных.

Классы библиотеки FCL предоставляют два способа явного выполнения таких преобразований:

  • метод Parse;
  • методы класса Convert.

Метод Parse

Все скалярные типы (арифметический, логический, символьный) имеют статический метод Parse, аргументом которого является строка, а возвращаемым результатом - объект соответствующего типа. Понятно, что строка, представляющая аргумент вызова, должна соответствовать представлению данных соответствующего типа. Если это требование не выполняется, то в ходе выполнения метода возникнет исключительная ситуация. Приведу пример преобразования данных, выполняемых с использованием метода Parse.

static void InputVars() { string strInput; Console.WriteLine(INPUT_BYTE); strInput = Console.ReadLine(); byte b1; b1 = byte.Parse(strInput); Console.WriteLine(INPUT_INT); strInput = Console.ReadLine(); int n; n = int.Parse(strInput); Console.WriteLine(INPUT_FLOAT); strInput = Console.ReadLine(); float x; x = float.Parse(strInput); Console.WriteLine(INPUT_CHAR); strInput = Console.ReadLine(); char ch; ch = char.Parse(strInput); }

Здесь приглашение к вводу задается соответствующей строковой константой. Поскольку вызов метода Parse способен приводить к исключительной ситуации, корректно построенный ввод пользовательских данных предполагает помещение подобного вызова в охраняемый блок и построение соответствующего обработчика исключительной ситуации. Для краткости примера эта часть работы опущена.

Метод TryParse

На основе метода Parse работает метод TryParse, выполняющий разбор строки в охраняемом блоке и сигнализирующий об успешности преобразования в возвращаемом булевском значении. В качестве побочного действия данный метод записывает в свой выходной аргумент результат преобразования.

static void InputTryParse() { string strInput = Console.ReadLine(); int n; if (! int.TryParse(strInput, out n)) Console.WriteLine(“Не удалось осуществить разбор строки! ”);

}






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.