День сорок седьмой. #ЗаметкиНаПолях
Приведение типов или Convert.To()
Несмотря на то, что эти операции могут казаться эквивалентными, они совершенно разные по целям.
Приведение типа – это действие по изменению объекта из одного типа данных в другой. Это достаточно общее определение, и в некотором смысле оно похоже на конвертацию, поскольку приведение типа часто имеет тот же синтаксис, что и конвертация. Поэтому возникает вопрос, когда достаточно приведения типа (неявного или явного), а когда вам придётся использовать более явную конвертацию.
Формально приведение типа изменит тип, тогда как конвертация изменит (или может изменить) значение (вместе с типом). Также приведение типа обратимо, тогда как конвертация может быть необратимой.
Неявные приведения типов
В C# приведение типа происходит неявно, когда вы не теряете информацию (заметьте, что эта проверка происходит на уровне типов, а не на уровне реальных значений переменных). Например, для примитивных типов:
Явные приведения типов
Приведение типа явно, когда оно не может быть выполнено неявно компилятором, и вам нужно использовать оператор приведения типа. Обычно это значит, что:
1. Вы можете потерять информацию или данные.
2. Преобразование может завершиться неудачей (поскольку вы не можете привести один тип к другому).
Явное преобразование подразумевает, что вы понимаете эти угрозы.
Для примитивных типов:
Приведение типов или Convert.To()
Несмотря на то, что эти операции могут казаться эквивалентными, они совершенно разные по целям.
Приведение типа – это действие по изменению объекта из одного типа данных в другой. Это достаточно общее определение, и в некотором смысле оно похоже на конвертацию, поскольку приведение типа часто имеет тот же синтаксис, что и конвертация. Поэтому возникает вопрос, когда достаточно приведения типа (неявного или явного), а когда вам придётся использовать более явную конвертацию.
Формально приведение типа изменит тип, тогда как конвертация изменит (или может изменить) значение (вместе с типом). Также приведение типа обратимо, тогда как конвертация может быть необратимой.
Неявные приведения типов
В C# приведение типа происходит неявно, когда вы не теряете информацию (заметьте, что эта проверка происходит на уровне типов, а не на уровне реальных значений переменных). Например, для примитивных типов:
int tinyInteger = 10;Эти приведения неявны, поскольку при этом вы не теряете информацию (вы расширяете тип). В обратную сторону неявное приведение невозможно, потому что вне зависимости от реальных значений (они проверяются только во время выполнения) при приведении вы можете потерять часть данных. Например, следующий код не скомпилируется, потому что тип
long bigInteger = tinyInteger;
float tinyReal = 10.0f;
double bigReal = tinyReal;
double
может содержать значения, не представленные в типе float
:double bigReal = Double.MaxValue;Для объектов приведение типов всегда неявно, когда компилятор уверен, что исходный тип – производный класс от целевого или реализует целевой интерфейс, например:
float tinyReal = bigReal;
string text = "123";В этих случаях информация не теряется, поскольку объекты не меняют своих типов, меняется только то, в каком типе вы их представляете.
IFormattable formattable = text;
NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;
Явные приведения типов
Приведение типа явно, когда оно не может быть выполнено неявно компилятором, и вам нужно использовать оператор приведения типа. Обычно это значит, что:
1. Вы можете потерять информацию или данные.
2. Преобразование может завершиться неудачей (поскольку вы не можете привести один тип к другому).
Явное преобразование подразумевает, что вы понимаете эти угрозы.
Для примитивных типов:
double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);В обоих примерах, несмотря на то, что значения входят в диапазон типа
float coarse = (float)precise;
float epsilon = (float)Double.Epsilon;
float
, вы теряете информацию (точность), поэтому преобразование должно быть явным. А такое приведение завершится неудачей:float max = (float)Double.MaxValue;А следующее преобразование не скомпилируется, поскольку компилятор не умеет преобразовывать текст в число. Текст может содержать любые символы, не только цифры, поэтому в C# это недопустимо (хотя может быть допустимо в других языках):
string text = "123";Преобразования объектов могут завершиться неудачей, если типы несвязанные. Например, код ниже не скопмилируется:
double value = (double)text;
string text = (string)AppDomain.Current;Следующий код скомпилируется, но он может привести к ошибке времени выполнения
Exception exception = (Exception)"abc";
InvalidCastException
в зависимости от реального типа объекта: