В книге Джесси Либерти Learning C# он говорит: «Объекты одного типа могут быть преобразованы в объекты другого типа. Это называется преобразованием».
Если вы исследуете IL, сгенерированный из приведенного ниже кода, вы можете ясно увидеть, что приведенное присвоение не выполняет то же самое, что преобразованное присвоение. В первом случае вы можете увидеть, как происходит упаковка / распаковка; в последнем вы можете увидеть вызов метода convert.
Я знаю, что в конце концов это может быть просто глупая семантическая разница - но это просто другое слово для преобразования. Я не хочу показаться язвительным, но меня не интересует чье-то внутреннее чутье по этому поводу - мнения здесь не в счет! Может ли кто-нибудь указать на исчерпывающую ссылку, которая подтверждает или отрицает, что литье и преобразование - это одно и то же?
object x;
int y;
x = 4;
y = ( int )x;
y = Convert.ToInt32( x );
Спасибо
rp
Примечание добавлено после комментария Мэтта о явном / неявном:
Я не думаю, что явная / явная разница. В опубликованном мной коде изменение явное в обоих случаях. Неявное преобразование - это то, что происходит, когда вы назначаете short для int.
Примечание для Скливвз:
Я хотел подтверждения того, что мои подозрения относительно расплывчатости языка Джесси Либерти (обычно ясного и ясного) были правильными. Я подумал, что Джесси Либерти немного растерялся со своим языком. Я понимаю, что приведение выполняется в иерархии объектов, т. Е. Вы не можете преобразовать целое число в строку, но вы можете преобразовать пользовательское исключение, полученное из System.Exception, в System.Exception.
Однако интересно, что когда вы все же пытаетесь преобразовать int в строку, компилятор сообщает вам, что он не может «преобразовать» значение. Может, Джесси более прав, чем я думал!
@JohannesRudolph, кстати, этот вопрос старше.





Разница в том, явное или неявное преобразование. Первый - это приведение, второй - более явный вызов функции, которая преобразует. Вероятно, они делают одно и то же по-разному.
Точно нет!
Convert пытается получить Int32 "любыми возможными способами". Cast ничего подобного не делает. С помощью cast вы указываете компилятору обрабатывать объект как Int без преобразования.
Вы всегда должны использовать приведение, если знаете (по дизайну), что объект является Int32 или другим классом, который имеет оператор приведения к Int32 (например, float).
Convert следует использовать с String или с другими классами.
Попробуй это
static void Main(string[] args)
{
long l = long.MaxValue;
Console.WriteLine(l);
byte b = (byte) l;
Console.WriteLine(b);
b = Convert.ToByte(l);
Console.WriteLine(b);
}
Результат:
9223372036854775807
255
Unhandled Exception:
System.OverflowException: Value is greater than Byte.MaxValue or less than Byte.MinValue at System.Convert.ToByte (Int64 value) [0x00000] at Test.Main (System.String[] args) [0x00019] in /home/marco/develop/test/Exceptions.cs:15
Обратите внимание на явные операторы преобразования. Это может вызвать непредвиденное поведение, особенно потерю ссылок.
Приведение сообщает компилятору / интерпретатору, что объект на самом деле относится к этому типу (или имеет базовый тип / интерфейс этого типа). Это довольно быстро по сравнению с преобразованием, когда работу выполняет не компилятор / интерпретатор, а функция, запускающая синтаксический анализ строки и выполнение математических расчетов для преобразования в число.
Кроме того, очевидны случаи, когда приведенный объект НЕ относится к типу, к которому приведено: double d = 3.14159; int i = (int) d; Двойное значение не является типом int; и ни один из них не является двойным. Между ними есть только явное приведение.
Приведение всегда означает изменение типа данных объекта. Это может быть сделано, например, путем преобразования значения с плавающей запятой в целочисленное значение или путем переинтерпретации битов. Обычно это операция, поддерживаемая языком (читай: поддерживаемая компилятором).
Термин «преобразование» иногда используется для приведения типов, но обычно это делается какой-либо библиотекой или вашим собственным кодом и не обязательно приводит к тому же результату, что и приведение. Например, если у вас есть имперское значение веса и преобразовано его в метрический вес, он может остаться того же типа данных (скажем, с плавающей точкой), но стать другим числом. Другой типичный пример - преобразование градусов в радианы.
Мне нравится ваш ответ, но я не знаю, лучше ли его описать «тип данных».
Тип данных - это слово, которое я выучил для этого. Не стесняйтесь предложить более подходящее слово :)
если бы мы говорили строго о примитивах, это подходит, но когда вы переходите к приведению сложных классов, это больше не подходит. Хм, я не знаю, кроме "типа" :)
Приведение ссылочного типа определенно не меняет тип самого объекта. Он изменяет эффективный тип Справка.
Если вы выполняете приведение с помощью оператора явного или неявного приведения, который возвращает другой тип, изменение не обязательно происходит только в ссылке, потому что вы можете получить новый объект. С другой стороны, это то, что я имел в виду под «переосмыслением битов», хотя я не говорил о ссылочных типах.
Лучшее объяснение, которое я видел, можно увидеть ниже со ссылкой на источник:
"... На самом деле все немного сложнее. .NET предоставляет три способа как бы добраться из точки А в точку Б.
Во-первых, это неявное приведение. Это актерский состав, который не требовать от вас чего-то большего, чем задание:
int i = 5;
double d = i;
Их также называют «расширяющими преобразованиями», и .NET позволяет вам выполнять их без оператора приведения, потому что вы никогда не потеряете информация, делающая это: возможный диапазон допустимых значений двойного охватывает диапазон допустимых значений для int, а затем некоторых, поэтому вы никогда не сделаете это задание, а потом откроете для себя ужас, что среда выполнения упала на несколько цифр от вашего значения int. Для ссылочных типов, правило неявного приведения состоит в том, что приведение никогда не мог вызвать InvalidCastException: это ясно для компилятора что приведение всегда в силе.
Вы можете создавать новые неявные операторы приведения для ваших собственных типов (которые означает, что вы можете делать неявные преобразования, нарушающие все правила, если ты глуп на этот счет). Основное эмпирическое правило состоит в том, что неявное актерский состав никогда не может включать в себя возможность потери информации в переход.
Обратите внимание, что базовое представление сделал изменяется в этом преобразование: double представляется совершенно иначе, чем int.
Второй вид преобразования - это явное приведение. Явное приведение требуется везде, где есть возможность потери информации, или есть вероятность, что приведение может быть недействительным и, таким образом, бросить исключение InvalidCastException:
double d = 1.5;
int i = (int)d;
Здесь вы, очевидно, потеряете информацию: я буду 1 после cast, поэтому 0.5 теряется. Это также известно как «сужение». преобразование, а компилятор требует, чтобы вы включили явное приведение (int), чтобы указать, что да, вы знаете, что информация может быть потеряна, но тебе все равно.
Точно так же со ссылочными типами компилятор требует явных приведений в ситуации, в которых приведение может быть недействительным во время выполнения, как сигнал что да, вы знаете, что есть риск, но вы знаете, что делаете.
Третий вид обращения включает в себя такие радикальные изменения. в представлении, что дизайнеры не предоставили даже явного cast: они заставляют вас вызывать метод для преобразования:
string s = "15";
int i = Convert.ToInt32(s);
Обратите внимание, что здесь нет ничего, что требует вызова метода. Неявное и явное приведение типов также являются вызовами методов (именно так вы делаете твой собственный). Дизайнеры легко могли создать явный оператор приведения, который преобразовал строку в int. Требование, чтобы Вы называете метод - это скорее стилистический выбор, чем фундаментальный требование языка.
Стилистическое рассуждение выглядит примерно так: String-to-int - это сложная конверсия с множеством возможностей для работы ужасно неправильно:
string s = "The quick brown fox";
int i = Convert.ToInt32(s);
Таким образом, вызов метода дает вам документацию для чтения и широкий намек на то, что это нечто большее, чем просто быстрое заклинание.
При разработке ваших собственных типов (особенно ваших собственных типов значений) вы может решить создать операторы приведения и функции преобразования. Линии разделение "неявного приведения", "явного приведения" и "функции преобразования" территории немного размыты, поэтому разные люди могут делать разные решения относительно того, что должно быть чем. Просто постарайся иметь в виду потеря информации и возможность исключений и недействительных данных, а также это должно помочь вам принять решение ".
http://bytes.com/forum/post1068532-4.html
Обратите внимание, что приведение длинного значения к двойному считается «расширяющимся» приведением, даже если это преобразование из типа «точного значения», которое может привести к тому, что новая переменная не будет содержать то же значение, что и старая. К сожалению, несмотря на решение Microsoft использовать одиночные числа для аргументов многих графических функций и несмотря на то, что двойное значение по своей сути является типом «приблизительного значения», Microsoft считает, что преобразование двойного в> одиночное с относительно меньшими потерями является «сужением. ".
В манере речи, не зависящей от языка / фреймворка, преобразование из одного типа или класса в другой называется Кастинг. Это верно и для .NET, как показывают ваши первые четыре строки:
object x;
int y;
x = 4;
y = ( int )x;
C и C-подобные языки (например, C#) используют синтаксис (newtype)somevar для приведения типов. В VB.NET, например, для этого есть явные встроенные функции. Последняя строка будет записана так:
y = CInt(x)
Или для более сложных типов:
y = CType(x, newtype)
Где «C», очевидно, является сокращением от «cast».
Однако .NET также имеет функцию Convert(). Это не встроенная функция языка (в отличие от двух вышеупомянутых), а скорее одна из фреймворков. Это становится яснее, когда вы используете язык, который не обязательно используется вместе с .NET: они, скорее всего, все еще имеют свои собственные средства преобразования, но .NET добавляет Convert().
Как говорит Мэтт, разница в поведении заключается в том, что Convert() более явный. Вместо того, чтобы просто указывать компилятору обрабатывать y как целочисленный эквивалент x, вы специально указываете ему изменить x таким образом, чтобы он подходил для целочисленного класса, потом присвоит результат y.
В вашем конкретном случае приведение выполняет то, что называется «распаковкой», тогда как Convert() фактически получит целочисленное значение. Результат будет таким же, но есть небольшие отличия лучше объяснил Кит.
Приведение по сути просто говорит среде выполнения «притвориться», что объект является новым типом. На самом деле он никоим образом не преобразует и не изменяет объект.
Однако Convert будет выполнять операции по превращению одного типа в другой.
Например:
char caster = '5';
Console.WriteLine((int)caster);
Результатом этих операторов будет 53, потому что все, что делала среда выполнения, это смотрело на битовый шаблон и рассматривало его как int. В итоге вы получите значение ascii символа 5, а не число 5.
Однако, если вы используете Convert.ToInt32 (caster), вы получите 5, потому что он фактически считывает строку и правильно ее изменяет. (По сути, он знает, что значение ASCII 53 на самом деле является целым числом 5.)
Не большая разница, но все равно обновил. ;) Пример по-прежнему работает независимо от среды выполнения или компилятора, и я думаю, что в любом случае это дает реальную точку зрения ...
Примечание для себя: используйте вырезание / вставку, а не вводите текст в крошечном окне редактора. Спасибо, что указали на ошибку!
Ответ прост: это зависит от обстоятельств.
Для типов значений приведение будет включать в себя подлинное преобразование их в другой тип. Например:
float f = 1.5f;
int i = (int) f; // Conversion
Когда выражение приведения распаковывается, результатом (при условии, что оно работает) будет как правило просто копия того, что было в коробке, с тем же типом. Однако есть исключения - вы можете распаковать из упакованного int в перечисление (с базовым типом int) и наоборот; аналогично вы можете распаковать из упакованного int в Nullable <int>.
Когда выражение приведения относится от одного ссылочного типа к другому и не задействовано определяемое пользователем преобразование, преобразование не происходит в том, что касается самого объекта - только "изменяется" тип Справка - и это действительно единственный способ, которым рассматривается значение, а не сама ссылка (это будут те же биты, что и раньше). Например:
object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object
Когда участвуют определяемые пользователем преобразования, этот как правило влечет за собой возврат другого объекта / значения. Например, вы можете определить преобразование в строку для своего собственного типа - и это определенно не будут те же данные, что и ваш собственный объект. (Конечно, это может быть существующая строка, на которую уже ссылается ваш объект.) По моему опыту, определяемые пользователем преобразования обычно существуют между типами значений, а не ссылочными типами, поэтому это редко является проблемой.
Все это считается преобразованием с точки зрения спецификации, но не все они считаются преобразованием объект в объект другого типа. Я подозреваю, что это случай, когда Джесси Либерти теряет терминологию - я заметил это в Программе C# 3.0, которую я только что прочитал.
Это все покрывает?
одна очень важная вещь заключается в том, что если вы работаете со строковыми сохраненными числами, это то, что (int) "" = сбой, в то время как Convert.ToInt32 ("") = 0, а также длинное десятичное значение в строке не будет правильно преобразовываться для культуры и сбой при cast, но отлично работает с Convert.ToDecimal ()
List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;
Обратите внимание, что операции с myList, такие как добавление элемента, отражаются в myEnumerable и myOtherList. Это потому, что все они являются ссылками (разного типа) на один и тот же экземпляр.
Апкастинг безопасен. Приведение вниз может вызвать ошибки времени выполнения, если программист допустил ошибку в типе. Этот ответ выходит за рамки безопасного низкочастотного анализа.
List<int> myList = new List<int>();
int[] myArray = myList.ToArray();
myList используется для создания myArray. Это неразрушающее преобразование (myList отлично работает после этой операции). Также обратите внимание, что операции с myList, такие как добавление элемента, не отражаются в myArray. Это потому, что это полностью отдельные экземпляры.
decimal w = 1.1m;
int x = (int)w;
Есть операции, использующие синтаксис приведения в C#, то есть фактически конверсии.
Не совсем ... вы не можете изменить тип ссылки или тип экземпляра. Вы получаете НОВУЮ ссылку другого типа на тот же объект и получаете НОВЫЙ объект или структуру другого типа.
Отредактировано, этот ответ лучше?
Согласно Таблице 1-7, озаглавленной «Методы явного преобразования» на стр. 55 в Главе 1, Урок 4 Комплект для самостоятельного обучения MCTS (экзамен 70-536): Microsoft® .NET Framework 2.0 - Application Development Foundation, между ними определенно есть разница.
System.Convert не зависит от языка и преобразует «между типами, реализующими System.IConvertible интерфейс».
(тип) оператор приведения - это функция языка Специфично для C#, которая преобразует «Между типами, которые определяют операторы преобразования».
Кроме того, при реализации пользовательских преобразований совет отличается между ними.
Согласно разделу под названием Как реализовать преобразование в пользовательских типах на стр. 56-57 в приведенном выше уроке, операторы преобразования (приведение) предназначены для упрощения преобразований между числовыми типами, тогда как Convert () обеспечивает преобразования, зависящие от языка и региональных параметров..
Which technique you choose depends on the type of conversion you want to perform:
Define conversion operators to simplify narrowing and widening conversions between numeric types.
Implement System.IConvertible to enable conversion through System.Convert. Use this technique to enable culture-specific conversions.
...
Теперь должно быть более ясно, что, поскольку оператор преобразования приведения реализован отдельно от интерфейса IConvertible, Convert () не обязательно является просто другим именем для приведения. (Но я могу представить, где одна реализация может ссылаться на другую для обеспечения согласованности).
Помимо семантики, быстрый тест показывает, что они НЕ эквивалент!
Они по-разному выполняют задачу (или, возможно, выполняют разные задачи).
x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2
Обратите внимание на случаи x=-1.5 и x=1.5.
Приведение округляется к нулю. msdn.microsoft.com/en-us/library/yht2cx7b.aspx *** Convert применяет правила округления бухгалтерского учета. .5 округляется до ближайшего четного числа, в противном случае до ближайшего целого числа. msdn.microsoft.com/en-us/library/ffdk7eyz(VS.90).aspx
возможный дубликат (но у этого есть ответы получше): stackoverflow.com/questions/3166840/…