Кастинг, распаковка, конвертация ..? - PullRequest
3 голосов
/ 19 января 2011

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

int x = (int)2.5; //casting?

object a=x;
int Y=(int)a;  //unboxing I think

Random r=new Random();
object X=r;
Random R=(Random)X;  // casting

Ответы [ 5 ]

8 голосов
/ 19 января 2011

Здесь нужно учесть много вещей, но давайте сначала займемся самым простым:

Какой синтаксис (type)expression?

Ну, в своей основной форме это считается кастингом. Вы приводите выражение от одного типа к другому. Вот и все.

Однако, что именно происходит, это зависит от типа и многих других вещей.

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

То, что делает этот оператор, зависит от автора этого оператора. Это метод, поэтому он может делать что угодно.

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

Пример:

int a = (int)byteValue;

Упаковка и распаковка вступают в игру, когда вы приводите тип значения в ссылочный тип и из него, обычно object, или в один из интерфейсов, которые реализует тип значения.

* * Пример тысяча двадцать-один: * * 1 022
object o = intValue; // boxing
int i = (int)o;      // unboxing

Бокс также вступает в игру при приведении к интерфейсу. Давайте предположим, что someValueType является структурой, которая также реализует IDisposable:

IDisposable disp = (IDisposable)someValueType; // boxed

Приведение ссылочного типа также может делать что-то еще.

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

Бокс не вступает в игру при приведении ссылочного типа, если вы не приведете ссылочный тип обратно к типу значения (см. Выше).

* +1034 * Пример: * * одна тысяча тридцать пять
string s = (string)myObjectThatCanBeConvertedToAString;

Или вы можете просто переосмыслить ссылку, чтобы вы все равно ссылались на тот же объект, о котором идет речь, но смотрели на него через другую пару очков типа.

* +1039 * Пример:
IDisposable disp = (IDisposable)someDisposableObject;
2 голосов
/ 19 января 2011

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

int myInt = 1;
object x = myInt; // box
int  unbox1 = (int)x;  // successful unbox
int? unbox2 = (int?)x; // successful unbox
long unbox3 = (long)x; // error. Can't unbox int to long
long unbox4 = (long)(int)x; // works. First it unboxes to int, and then converts to long

Другим интересным моментом является то, что тип значения, допускающий значение NULL, упаковывается как его тип, не допускающий значения NULL, и может быть распакован как тип NULL и NULL.Так как обнуляемое значение null указывает на ссылку null, информация о его типе теряется во время бокса.

1 голос
/ 19 января 2011

Приведение - это одна из форм конвертации, в основном.

Все комментарии в вашем коде верны.

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

Сравните этос преобразованием double в int (значительно изменяет форму) и распаковкой (копирует значение из поля в переменную).

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

1 голос
/ 19 января 2011

Бокс и распаковка, в частности, относятся к приведению типов значений к ссылочным типам и обратно.Перейдите по этой ссылке, чтобы узнать больше Бокс и распаковка (Руководство по программированию в C #) .

0 голосов
/ 19 января 2011

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

int x = (int)2.5; //casting with conversion

object a=x; //casting with boxing
int Y=(int)a;  //casting with unboxing

Random r=new Random();
object X=r;
Random R=(Random)X;  //casting without unboxing

о кастинге против конверсии проверьте этот вопрос: В чем разница между кастингом и конверсией?

...