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

Бокс против Unboxing

Еще один недавний вопрос интервью с С#, который у меня был, был, если бы я знал, что такое бокс и Unboxing. Я объяснил, что типы значений относятся к типам Stack и Reference в Heap. Когда значение передается в ссылочный тип, мы называем его боксом и наоборот.

Затем он попросил меня рассчитать это:

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, и это так. Но это совсем не пример бокса/распаковки, это правильно? Итак, как бы вы это обобщили?

Могут ли значения когда-либо стать одинаковыми в преобразовании бокса/распаковки, как указано выше?

4b9b3361

Ответ 1

  • Вы правы, второе присваивание заменяет первое. Он не меняет значение в коробке.

  • В вашем примере не используется бокс. Значение (int) сохраняется как int, а не в коробке.

  • Нет, бокс по-прежнему сохраняет гарантию неизменности.

Ответ 2

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

То, что вы делаете с a = 2, не меняет значение в поле "box", вы создаете новый экземпляр ссылочного типа. Так почему же нужно что-то менять?

Ответ 3

Я ожидал увидеть b == 2, но это не так, почему? это потому, что второй бокс разрушает и заменяет весь (а) -объект на куче?

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

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

Невозможно изменить даже измененную структуру типа Point при вставке. Чтобы получить доступ к свойствам структуры, вам необходимо распаковать ее, поэтому вы не можете изменить структуру вложенных блоков.

Ответ 4

Вот еще один интересный вариант, который поддерживает замечания Стефана:

        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

Ответ 5

b все равно 1, потому что b является ссылкой, которая все еще указывает на объект в куче со значением 1. a is 2, потому что вы назначили его новому объекту в куче со значением 2.

t2.x - 3, потому что t и t2 - две разные ссылки на один и тот же объект в куче.

Ответ 6

Я думаю, что ответ на ваш вопрос с unboxing заключается в следующем: результат преобразования unboxing является временной переменной (подробнее: ссылка).

Я думаю, вы пытались сделать так:

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, но это не так, почему? это потому, что второй бокс разрушает и заменяет весь (а) -объект на куче?