Каково различие между кастингом и преобразованием? [дубликат]

Этот вопрос уже имеет ответ здесь:

Комментарии Eric Lippert в этом вопросе оставили меня полностью смущенным. Каково различие между кастингом и преобразованием в C#?

67
задан Community 23 May 2017 в 12:34
поделиться

12 ответов

Я считаю, что Эрик пытается сказать следующее:

Приведение - это термин, описывающий синтаксис (отсюда синтаксическое значение).

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

Выражение приведения используется для преобразования явно выражение для данного тип.

И

Приведение-выражение формы (T) E, где T - тип, а E - унарное выражение, выполняет явное преобразование (§13.2) значения E для ввода T.

Похоже, это подтверждается заявлением о том, что оператор приведения в синтаксисе выполняет явное преобразование.

45
ответ дан 24 November 2019 в 14:28
поделиться

Приведение и преобразование - это в основном та же концепция в C #, за исключением того, что преобразование может быть выполнено с использованием любого метода, такого как Object.ToString () . Приведение выполняется только с помощью оператора приведения (T) E , который описан в других сообщениях, и может использовать преобразования или бокс.

Какой метод преобразования он использует? Компилятор принимает решение на основе классов и библиотек, предоставленных компилятору во время компиляции. Если существует неявное преобразование, вам не требуется использовать оператор приведения. Объект o = String.Empty . Если существуют только явные преобразования, вы должны использовать оператор приведения. Строка s = (Строка) или .

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

Приведение всегда относится к использованию оператора приведения. Вы можете написать

Object o = float.NaN;
String s = (String) o;

, но если вы получите доступ к s , например, в Console.WriteLine , вы получите время выполнения InvalidCastException . Таким образом, оператор приведения все еще пытается использовать преобразование во время доступа, но соглашается на бокс во время присваивания.

0
ответ дан 24 November 2019 в 14:28
поделиться

Приведение - это способ сказать компилятору: «Объект X действительно является Типом Y, продолжайте и относитесь к нему как к таковому».

Преобразование говорит: «Я знаю, что объект X не является типом Y, но существует способ создать новый объект из X типа Y, продолжайте и сделайте это».

80
ответ дан 24 November 2019 в 14:28
поделиться

Мне вспоминается анекдот, рассказанный Ричардом Фейнманом, когда он посещает класс философии, и профессор спрашивает его: «Фейнман, ты физик, по твоему мнению, электрон "существенный объект"? " Итак, Фейнман задает уточняющий вопрос: «Является ли кирпич важным объектом?» к классу. У каждого ученика свой ответ на этот вопрос. Они говорят, что существенным объектом является фундаментальное абстрактное понятие «кирпичность». Нет, один конкретный, уникальный кирпич - это предмет первой необходимости. Нет, части кирпича, которые вы можете наблюдать эмпирически, являются существенным объектом. И так далее.

Что, конечно, не для ответа на ваш вопрос.

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

А как насчет аналогии а-ля Фейнман? Вы хотите испечь буханку бананового хлеба в субботу утром (как я делаю почти каждое субботнее утро). Итак, вы обратитесь к The Joy of Cooking, и там написано: «бла-бла-бла… В другой миске смешайте сухие ингредиенты. .."

Очевидно, что существует тесная связь между этой инструкцией и вашими действиями завтра утром, но столь же ясно, что было бы ошибкой объединять инструкцию с действием . Инструкция состоит из текста. Это место на определенной странице. В нем есть знаки препинания. Если бы вы были на кухне, взбивая муку и пищевую соду, и кто-то спросил бы: «Какая у вас сейчас пунктуация?», вы бы, вероятно, подумали, что это было. странный вопрос. Действие связано с инструкцией, но текстовые свойства инструкции не являются свойствами действия.

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

42
ответ дан 24 November 2019 в 14:28
поделиться

После прочтения комментариев Эрика, попытка на простом английском:

Casting означает, что два типа фактически одинаковы на каком-то уровне. Они могут реализовывать один и тот же интерфейс или наследоваться от одного базового класса, или объект может быть достаточно "одинаковым" (супермножество?), чтобы приведение сработало, например, приведение из Int16 в Int32.

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

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

5
ответ дан 24 November 2019 в 14:28
поделиться

В этом контексте приведение означает, что вы открываете объект данного типа для манипуляции как некоторый другой тип, преобразование означает, что вы фактически меняете объект данного типа на объект другого типа.

1
ответ дан 24 November 2019 в 14:28
поделиться

Эта страница документации MSDN C# говорит о том, что приведение - это особый случай преобразования: "явное преобразование". То есть, преобразование вида x = (int)y - это приведение.

Автоматическое изменение типа данных (например, myLong = myInt) - это более общее "преобразование"

.
0
ответ дан 24 November 2019 в 14:28
поделиться

Просто мое понимание, возможно, слишком простое:

При преобразовании основные данные остаются нетронутыми (такое же внутреннее представление) - «Я знаю, что это словарь, но вы можете использовать его как ICollection».

При преобразовании вы меняете внутреннее представление на другое - «Я хочу, чтобы этот int был строкой».

6
ответ дан 24 November 2019 в 14:28
поделиться

Приведение - это оператор класса / структуры. Преобразование - это метод / процесс одного или другого затронутого класса / структуры или может быть в совершенно другом классе / структуре (например, Converter.ToInt32 ()

Операторы приведения бывают двух видов: неявные и явные

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

int i = 25;
decimal d = i;

] Явные операторы приведения указывают, что данные одного типа (десятичные) могут всегда быть точно представлены как другой тип (int), но могут быть потери данных / точности.Поэтому компилятор требует, чтобы вы явно заявили, что вы знаете об этом и хотите сделать это в любом случае, с помощью явного синтаксиса приведения:

decimal d = 25.0001;
int i = (int)d;

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

string s = "200";
int i = Converter.ToInt32(s); // set i to 200 by parsing s

string s = "two hundred";
int i = Converter.ToInt32(s); // sets i to 0 because the parse fails

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

0
ответ дан 24 November 2019 в 14:28
поделиться

Приведение является синтаксическим и может включать или не включать преобразование (в зависимости от типа приведения). Как вы знаете, C ++ позволяет указать тип приведения , который вы хотите использовать.

Приведение вверх / вниз по иерархии может рассматриваться или не рассматриваться как преобразование, в зависимости от того, кого вы спрашиваете (и на каком языке они говорят!)

Эрик (C #) говорит, что приведение к другому Тип всегда включает преобразование, хотя это преобразование может даже не изменить внутреннее представление экземпляра.

Специалист по C ++ не согласится, поскольку static_cast может не привести к дополнительному коду (так что «преобразование» на самом деле нереально!)

0
ответ дан 24 November 2019 в 14:28
поделиться

Из спецификации C # 14.6.6:

Выражение приведения используется для преобразования явно выражение для данного тип.
...
Приведение-выражение вида (T) E, где T - тип, а E - унарное выражение, выполняет явное преобразование (§13.2) значения E для типа T.

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

Из C # Spec §13:

Преобразование позволяет выражение один тип должен рассматриваться как другой тип. Преобразования могут быть неявными или явный, и это определяет, требуется явное приведение. [Пример: например, преобразование от типа int к типу long неявный, поэтому выражения типа int может неявно рассматриваться как тип длинный. Противоположное преобразование, от type long для типа int, является явным, поэтому требуется явное приведение.

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

7
ответ дан 24 November 2019 в 14:28
поделиться

Casting - это создание значения одного типа из другого значения другого типа. Конвертация - это тип приведения, при котором внутреннее представление значения также должно быть изменено (а не только его интерпретация).

В C# приведение и преобразование выполняются с помощью cast-выражения:

( type ) unary-expression

Различие важно (и об этом говорится в комментарии), потому что только преобразования могут быть созданы conversion-operator-declarator. Поэтому в коде могут быть созданы только (неявные или явные) преобразования.

Неявное приведение без преобразования всегда доступно для приведения подтипа к супертипу, а явное приведение без преобразования всегда доступно для приведения супертипа к подтипу. Никакие другие неконверсионные приведения не допускаются.

2
ответ дан 24 November 2019 в 14:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: