Языки программирования

Преобразование типов данных в C#

В языке C# допускается преобразование типов данных с их автоматическим сужением и расширением. Рассмотрим следующий пример:
using System;

namespace HelloWorld
{
   class Program
   {
       static void Main (string[] args)
       {
          short a = 2000, b = 4000;
          int c = Add(a, b);
          Console.WriteLine("c = {0}", c);
          Console.ReadLine();
       }
       static int Add(int a, int b)
       {
            return a + b;
       }
   }
}
В данном примере в метод Add() мы передаём два значения типа short, хотя метод подразумевает приём параметров типа int. Тип short поглощается типом int. Расширение всегда происходит без потери данных, поэтому вы увидите правильный результат:
c = 6000
Рассмотрим этот же пример, но немного его изменим. Попытка скомпилировать его приведет к ошибке компиляции.
using System;

namespace HelloWorld
{
   class Program
   {
       static void Main (string[] args)
       {
          short a = 20000, b = 20000;
          short c = Add(a, b);
          Console.WriteLine("c = {0}", c);
          Console.ReadLine();
       }
       static int Add(int a, int b)
       {
            return a + b;
       }
   }
}
Во-первых, мы увеличили значения переменных a и b. Во-вторых, переменная c теперь типа short, а не int. Переменные типа short передаются в качестве параметров методу Add(). Компилятор может выполнить расширение до типа int, как было отмечено ранее, но ему приходится возвращать ответ типа int, который нужно поместить в переменную типа short.

Выполнить сужение типа без потери данных в этом случае невозможно. Результат будет 40000, а максимальное значение для short 32767. Поэтому компилятор выдаст ошибку.

Чтобы заставить компилятор выполнить сужение типа с потерей данных, нужно использовать операцию явного приведения типов. В C# данная операция обозначается с помощью скобок (), внутри которых приводится имя типа, к которому нужно привести значение:
short c = (short)Add(a, b);
Программа будет выполнена, но результат будет неправильным:
c = -25536
Во многих приложениях, особенно финансовых, такие потери данных недопустимы. Поэтому в C# предлагаются ключевые слова checked и unchecked, гарантирующие, что потеря данных окажется незамеченной.

Если оператор или блок оператора заключена в контекст checked, то компилятор сгенерирует дополнительные CIL-инструкции, обеспечивающие проверку на предмет условий перевыполнения, которые могут возникать в результате сложения, умножения, вычитания или деления двух числовых типов данных.

В случае возникновения условия переполнения во время выполнения будет генерироваться исключение System.OverflowException. Обработать исключение можно с помощью try/catch:
try
{ 
  short c = checked((short)Add(a, b));
  Console.WriteLine("c = {0}", c);
}
catch (OverflowException ex)
{
  Console.WriteLine(ex.Message);
}
Из-за того, что действие флага checked распространяется на всю арифметическую логику, в C# предусмотрено ключевое слово unсhecked, которое позволяет отключить выдачу связанного с переполнением исключения в отдельных случаях.
unchecked 
{
   short c = (short)Add(a, b);
   Console.WriteLine("c = {0}", c);
}
Использовать ключевое слово unchecked можно только в тех случаях, где переполнение является допустимым.
Самоучитель по C#