Бокс против Распаковки коробки
Вопрос
Еще один недавний вопрос в интервью C #, который у меня возник, касался того, знаю ли я, что такое упаковка и распаковка.Я объяснил, что типы значений находятся в стеке, а ссылочные типы - в куче.Когда значение преобразуется к ссылочному типу, мы называем это упаковкой, и наоборот.
Затем он попросил меня рассчитать это:
int i = 20;
object j = i;
j = 50;
Что такое i
?
Я все перепутал и сказал 50, хотя на самом деле это 20.Теперь я, кажется, понимаю, почему, однако, когда я играл с разными комбинациями, я был удивлен, увидев это:
Object a = 1; // Boxing
Object b = a; // referencing the pointer on stack to both objects on heap
a = 2; // Boxing
Я ожидал увидеть b == 2
также, но это не так, почему?Это потому, что второй бокс разрушает и заменяет весь a
объект в куче?
Потому что, если я сделаю это, все будет в порядке:
public class TT
{
public int x;
}
TT t = new TT();
t.x = 1;
TT t2 = new TT();
t2.x = 2;
t = t2;
t.x = 3;
Что такое t2.x
?Должно быть 3, и это так.Но это вообще не пример упаковки / распаковки, правильно ли это?Итак, как бы вы подытожили это?
Могут ли значения когда-либо стать одинаковыми при преобразовании упаковки / распаковки, как указано выше?
Решение
Вы правы, второе задание заменяет первое.Это не изменяет значение в штучной упаковке.
В вашем примере не используется бокс.Значение (int) сохраняется как int и не помещается в коробку.
Нет, бокс по-прежнему сохраняет гарантию неизменности.
Другие советы
Очень короткий:бокс означает создание нового экземпляра ссылочного типа.Если вы знаете это, вы понимаете, что один экземпляр не изменяется при создании другого.
Что вы делаете с a = 2
не изменяя значение в "поле", вы создаете новый экземпляр ссылочного типа.Так почему же что-то еще должно измениться?
Я также ожидал увидеть b == 2, но это не так, почему?это потому, что второй блок уничтожает и заменяет весь (a)-объект в куче?
Нет, не совсем.Он оставляет объект таким, какой он есть в куче (как b
переменная также ссылается на нее) и создает новый объект для нового значения, которое a
переменная будет ссылаться.
Вы правы в том, что во втором примере не используется boxing .Вы не можете получить доступ к значению, которое помещено в коробку, каким-либо другим способом, кроме как распаковав его, поэтому нет способа изменить значение в коробке.
Даже такой изменяемой структуры, как Point
может быть изменен при упаковке в коробку.Чтобы получить доступ к свойствам структуры, вы должны распаковать ее, поэтому вы не можете изменить структуру в штучной упаковке на месте.
Вот еще один интересный вариант, который подтверждает комментарии Стефана:
int i = 2;
object a = i; // Boxing
object b = a; // Referencing same address on heap as 'a', b == a
b = i; // New boxing on heap with reference new address, b != a
b по-прежнему равно 1, потому что b - это ссылка, которая по-прежнему указывает на объект в куче со значением 1.a равно 2, потому что вы присвоили его новому объекту в куче со значением 2.
t2.x равно 3, потому что t и t2 - это две разные ссылки на один и тот же объект в куче.
Я думаю, что ответ на ваш вопрос с распаковкой заключается в том, что:Результатом преобразования при распаковке является временная переменная (подробнее: Ссылка).
Я думаю, ты пытался сделать что-то вроде:
object a = new Point(10,10);
object b = new Point(20,20);
a = b;
((Point) b).X = 30; //after this operation also a.X should be 30
Приведенный выше код не будет компилироваться - подробности по ссылке выше, и я думаю, что это ответ на ваш вопрос:
Я также ожидал увидеть b == 2, но это не так, почему?это потому, что второй блок уничтожает и заменяет весь (a)-объект в куче?