Подтвердить что ты не робот

Является ли такое же преобразование?

В книге Jesse Liberty Learning С# он говорит: "Объекты одного типа могут быть преобразованы в объекты другого типа. Это называется литье".

Если вы исследуете IL, сгенерированный из приведенного ниже кода, вы можете ясно видеть, что выбранное задание не делает то же самое, что и преобразованное присваивание. В первом вы видите, как происходит бокс/распаковка; в последнем вы можете увидеть вызов метода конвертации.

Я знаю, что в конце концов это может быть просто глупое смысловое различие - но это просто другое слово для преобразования. Я не хочу быть забавным, но меня это не интересует, потому что мнения здесь не считаются! Может ли кто-нибудь указать на окончательную ссылку, которая подтверждает или отрицает, что кастинг и преобразование - одно и то же?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

Спасибо

гр

Примечание добавлено после комментария Matt о явной/неявной:

Я не думаю, что подразумеваемая/явная разница. В опубликованном мной коде изменения в обоих случаях являются явными. Неявное преобразование - это то, что происходит, когда вы назначаете short для int.

Примечание для Sklivvz:

Я хотел подтвердить, что мое подозрение в ослаблении языка Джесси Свободы (иначе обычно ясное и ясное) было правильным. Я думал, что Джесси Либерти немного расстроен своим языком. Я понимаю, что кастинг маршрутизируется в иерархии объектов - т.е. Вы не можете отличать целое число с строкой, но вы можете использовать произвольное исключение, происходящее из System.Exception, в System.Exception.

Интересно, однако, что, когда вы пытаетесь сделать из int в строку, компилятор сообщает вам, что он не может "преобразовать" значение. Может быть, Джесси более прав, чем я думал!

4b9b3361

Ответ 1

Простой ответ: это зависит.

Для типов значений кастинг будет включать в себя подлинное преобразование его в другой тип. Например:

float f = 1.5f;
int i = (int) f; // Conversion

Когда выражение для литья отменяет, результат (при условии, что он работает) обычно представляет собой копию того, что было в поле, с тем же типом. Однако есть исключения - вы можете распаковать из вложенного int в enum (с базовым типом int) и наоборот; аналогичным образом вы можете распаковать из вложенного пакета int в Nullable <int> .

Когда выражение каста от одного ссылочного типа к другому и не связано с определенным пользователем преобразованием, нет никакого преобразования в отношении самого объекта - только тип ссылки "изменяется" - и это действительно только путь, которым считается значение, а не сама ссылка (которые будут такими же, как раньше). Например:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

Когда вовлечены пользовательские преобразования, обычно это приводит к возврату другого объекта/значения. Например, вы можете определить преобразование в строку для своего собственного типа - и  это, конечно, не те же данные, что и ваш собственный объект. (Конечно, это может быть уже существующая строка, ссылающаяся на ваш объект). По моему опыту, пользовательские преобразования обычно существуют между типами значений, а не ссылочными типами, поэтому это редко бывает проблемой.

Все они считаются конверсиями в терминах спецификации - но они не все считают преобразованием объекта в объект другого типа. Я подозреваю, что это случай, когда Джесси Либерти теряла терминологию - я заметил это в Программе С# 3.0, которую я только что читал.

Все это покрывает?

Ответ 2

Абсолютно нет!

Преобразование пытается получить вам Int32 через "любые возможные средства". Cast ничего не делает. С помощью cast вы говорите компилятору, чтобы рассматривать объект как Int, без преобразования.

Вы всегда должны использовать листинг, когда знаете (по дизайну), что объект является Int32 или другим классом, который имеет оператор литья в Int32 (например, float).

Преобразование должно использоваться с 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

Необработанное исключение:

Исправление System.OverflowException: значение больше, чем Byte.MaxValue или меньше чем Byte.MinValue на System.Convert.ToByte(значение Int64) [0x00000] в Test.Main(System.String [] args) [0x00019] в /home/marco/develop/test/Exceptions.cs:15

Ответ 3

Лучшее объяснение, которое я видел, можно увидеть ниже, за которым следует ссылка на источник:

"... Правда немного сложнее, чем это. три метода получения из точки А в точку В. Как бы то ни было.

Во-первых, есть неявный бросок. Это актеры, которые не вам нужно сделать что-то большее, чем задание:

int i = 5;
double d = i;

Они также называются "расширяющимися преобразованиями", а .NET позволяет выполнять их без какого-либо оператора трансляции, потому что вы никогда не потеряете ни одного информация делает это: возможный диапазон действительных значений двойной охватывает диапазон допустимых значений для int, а затем некоторых, поэтому вы никогда не станете выполнять это задание, а затем ужас, что во время выполнения выпало несколько цифр с вашего значения int. Для ссылочные типы, правило, лежащее в основе неявного литья, заключается в том, что приведение никогда не может вызвать InvalidCastException: это ясно для компилятора что приведение всегда действительным.

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

Обратите внимание, что базовое представление изменилось в этом преобразование: double представляется полностью иначе, чем int.

Второй вид преобразования - это явный перевод. Явное литье требуется везде, где есть возможность потерять информацию, или есть вероятность, что бросок может быть недействительным и, таким образом, выбросить InvalidCastException:

double d = 1.5;
int i = (int)d;

Здесь вы, очевидно, потеряете информацию: я буду 1 после литой, поэтому 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);

Таким образом, вызов метода дает вам документацию для чтения и широкий намек на то, что это нечто большее, чем просто быстрый бросок.

При разработке собственных типов (особенно ваших собственных типов значений) вы может принять решение о создании операторов трансляции и функций преобразования. Линии разделяя "неявный литой", "явный приведение" и "функцию преобразования", территория немного размыта, поэтому разные люди могут решения относительно того, что должно быть. Просто старайтесь иметь в виду потери информации и возможности для исключений и недопустимых данных, а также это поможет вам решить.

  • Брюс Вуд, 16 ноября 2005 г.

http://bytes.com/forum/post1068532-4.html

Ответ 4

Литье включает ссылки

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;

Существуют операции с использованием синтаксиса cast в С#, которые фактически конверсии.

Ответ 5

Семантика в сторону, быстрый тест показывает, что они НЕ эквивалентны!
Они выполняют задачу по-другому (или, возможно, выполняют разные задачи).

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.

Ответ 6

Листинг говорит компилятору/интерпертеру, что объект фактически имеет этот тип (или имеет базовый тип/интерфейс этого типа). Это довольно быстро, по сравнению с конвертированием, где он больше не выполняет компилятор/интерпертер, выполняющий задание, а выполняет функцию синтаксического анализа строки и делает математику для преобразования в число.

Ответ 7

Кастинг всегда означает изменение типа данных объекта. Это можно сделать, например, путем преобразования значения float в целочисленное значение или путем переинтерпретации бит. Это обычно поддерживается на языке (поддерживается чтение: компилятор).

Термин "преобразование" иногда используется для кастинга, но обычно это делается какой-то библиотекой или вашим собственным кодом и не обязательно приводит к тому же, что и к кастингу. Например, если у вас есть значение имперского веса и преобразовать его в метрический вес, он может оставаться одним и тем же типом данных (скажем, float), но становится другим числом. Другим типичным примером является преобразование из градусов в радиан.

Ответ 8

В языке -/framework - агностической манере речи, преобразование из одного типа или класса в другое называется литье. Это верно и для .NET, поскольку ваши первые четыре строки показывают:

object x;
int y;

x = 4;

y = ( int )x;

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.

В вашем конкретном случае кастинг делает то, что называется "unboxing", тогда как Convert() фактически получит целочисленное значение. Результат будет таким же, но есть более тонкие отличия описанные Китом.

Ответ 9

В соответствии с таблицей 1-7 под названием "Методы явного преобразования" на стр. 55 в главе 1, Урок 4 из MCTS Self-Paced Training Kit (экзамен 70-536): Microsoft®.NET Framework 2.0-приложение Development Foundation, существует определенная разница между ними.

System.Convert не зависит от языка и преобразует "Между типами, реализующими интерфейс System.IConvertible".

(тип) оператор литья - это функция языка С# -специфическая, которая преобразует "Между типами, которые определяют операторы преобразования".

Кроме того, при реализации пользовательских преобразований совет отличается между ними.

В разделе под названием Как реализовать преобразование в пользовательских типах на стр. 56-57 в приведенном выше уроке, операторы преобразования (литье) предназначены для упрощения конверсий между числовыми типами, тогда как Convert ( ) позволяет преобразование, специфичное для культуры.

Какой метод вы выбираете, зависит от типа преобразования, которое вы хотите выполнить:

  • Определите операторы преобразования, чтобы упростить сужение и расширение преобразования между числовыми типами.

  • Внедрите System.IConvertible, чтобы включить преобразование через System.Convert. Используйте этот метод, чтобы включить преобразования, специфичные для культуры.

  • ...

Теперь должно быть яснее, что, поскольку оператор преобразования кавычек реализован отдельно от интерфейса IConvertible, Convert() не обязательно является просто другим именем для кастинга. (Но я могу представить себе, где одна реализация может ссылаться на другую, чтобы обеспечить согласованность).

Ответ 10

Не забывайте другие методы литья и преобразования переменных: as, Parse, TryParse а также неявное литье между совместимыми типами данных.

На этом сайте есть хороший пример того, какие результаты для большинства методов: С# Бокс и Unboxing

Итак, учитывая эти выборочные переменные:

int i = 3, x;
long l;
string s = "5";

В принципе, вы можете иметь неявное литье между двумя совместимыми типами:

l = i;

Явное литье с использованием распаковки или ключевое слово как:

s = (string)i;
//or
s = i as string;

Явные преобразования с использованием методов из System.Convert:

i = System.Convert.ToInt32(s);

Явные преобразования с использованием методов из определенного типа данных:

i = int.Parse(s);
i = int.TryParse(s, x);

Явные преобразования с использованием методов из экземпляра переменной:

s = i.ToString();

Я думаю, что литье - это просто способ создания назначений между двумя совместимыми типами.

Преобразование - это если вам нужно явно скопировать значение из одного несовместимого типа в другой, и вы не можете доверять evil принуждение.

Некоторая хорошая информация также о MSDN: Преобразование отливок и типов

Ответ 11

Кастинг по существу просто говорит во время выполнения "притворяться", что объект является новым типом. Он фактически не конвертирует или не изменяет объект.

Convert, однако, будет выполнять операции, чтобы превратить один тип в другой.

В качестве примера:

char caster = '5';
Console.WriteLine((int)caster);

Результатом этих операторов будет 53, потому что все время выполнения - это просмотр битового шаблона и рассмотрение его как int. То, что вы получаете, это значение ascii символа 5, а не число 5.

Если вы используете Convert.ToInt32 (caster), вы получите 5, потому что он действительно читает строку и правильно ее изменяет. (По сути, он знает, что значение 53 ASCII действительно является целым числом 5.)

Ответ 12

Разница в том, является ли преобразование неявным или явным. Первый - это бросок, второй - более явный вызов функции, которая преобразуется. Они, вероятно, продолжают делать то же самое по-разному.