Ответ 1
-
Вы правы, второе присваивание заменяет первое. Он не меняет значение в коробке.
-
В вашем примере не используется бокс. Значение (int) сохраняется как int, а не в коробке.
-
Нет, бокс по-прежнему сохраняет гарантию неизменности.
Еще один недавний вопрос интервью с С#, который у меня был, был, если бы я знал, что такое бокс и 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, и это так. Но это совсем не пример бокса/распаковки, это правильно? Итак, как бы вы это обобщили?
Могут ли значения когда-либо стать одинаковыми в преобразовании бокса/распаковки, как указано выше?
Вы правы, второе присваивание заменяет первое. Он не меняет значение в коробке.
В вашем примере не используется бокс. Значение (int) сохраняется как int, а не в коробке.
Нет, бокс по-прежнему сохраняет гарантию неизменности.
Очень короткий: бокс означает создание нового экземпляра ссылочного типа. Если вы знаете это, вы понимаете, что один экземпляр не изменяется, создавая другой.
То, что вы делаете с a = 2
, не меняет значение в поле "box", вы создаете новый экземпляр ссылочного типа. Так почему же нужно что-то менять?
Я ожидал увидеть b == 2, но это не так, почему? это потому, что второй бокс разрушает и заменяет весь (а) -объект на куче?
Нет, не совсем. Он оставляет объект так же, как и в куче (поскольку переменная b
также ссылается на него) и создает новый объект для нового значения, которое будет ссылаться на переменную a
.
Вы правы, что ваш второй пример не использует бокс. Вы не можете получить доступ к значению, которое помещается в коробку любым другим способом, чем распаковывать его, поэтому невозможно изменить значение в коробке.
Невозможно изменить даже измененную структуру типа 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 is 2, потому что вы назначили его новому объекту в куче со значением 2.
t2.x - 3, потому что t и t2 - две разные ссылки на один и тот же объект в куче.
Я думаю, что ответ на ваш вопрос с 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, но это не так, почему? это потому, что второй бокс разрушает и заменяет весь (а) -объект на куче?