Где находится ссылка на объект и что происходит, когда вы передаете ссылку на объект по ссылке?

В контексте С#:

Предположим, следующий код...

public class Foo
    {
        MrObject object1;
        MrObject object2;
        MrObject object3;
        MrObject object4;

        MrStruct struct1;
        MrStruct struct2;
        MrStruct struct3;
        MrStruct struct4;

        int i;

        public Foo()
        {
            object1 = new MrObject(1);  /// Alpha
            object2 = new MrObject(2);  /// Bravo
            object3 = new MrObject(3);  /// Charlie
            object4 = new MrObject(4);  /// Delta

            i = 1;

            InitializeComponent(); // POINT A
            ByValByRef(object1, ref object2);

        }


        public void ByValByRef(MrObject o1, ref MrObject o2)
        {
            o1.foo = 5; // POINT B
            o1 = object3; // POINT C
            o2.foo = 6; // POINT D
            o2 = object4; // POINT E
            return;
        }

Насколько я понимаю, в // ТОЧКЕ A вы создали четыре экземпляра MyObject. Эти четыре экземпляра живут в куче. - у вас есть четыре ссылки на эти экземпляры. ВОПРОС 1. Где они живут?

Насколько я понимаю, в // ТОЧКЕ B вы создали новую ссылку на «Альфа» с именем «o1». Эта ссылка добавляется и живет в стеке. Когда метод возвращается, эта ссылка удаляется.
— у вас есть ссылка с именем 'o2'. ВОПРОС 2: Является ли это новой ссылкой, которая добавляется и живет в стеке и ссылается на ссылку 'object2'? Или «o2» просто псевдоним, поддерживаемый в коде (а не в памяти), и на самом деле в памяти все еще есть только одна ссылка на «Браво», называемая «object2», и когда этот код фактически выполняется, «o2.foo» обрабатывается как «object2.foo»?


person chopperdave    schedule 28.02.2012    source источник


Ответы (1)


Насколько я понимаю, в // ТОЧКЕ A вы создали четыре экземпляра MyObject. Эти четыре экземпляра живут в куче.

Правильно. Память была выделена в куче для каждого объекта.

у вас есть четыре ссылки на эти экземпляры. ВОПРОС 1: Где они живут?

Когда вы создали объекты, вы назначили (ссылку) каждому из них на другое поле в объекте Foo. Эти поля «живут» в памяти, выделенной для объекта Foo, который почти наверняка также находится где-то в куче.

Насколько я понимаю, в // ТОЧКЕ B вы создали новую ссылку на «Альфа» с именем «o1». Эта ссылка добавляется и живет в стеке. Когда метод возвращается, эта ссылка удаляется.

Да, в ТОЧКЕ B параметр o1 также хранит ссылку на MrObject, который был передан в качестве аргумента. o1 живет в краткосрочном хранилище, которое в общем случае будет "стеком". Когда метод завершится, место в краткосрочном хранилище, используемое для o1, будет доступно для другого использования, и сборщик мусора больше не будет рассматривать o1 как известный живой корень.

у вас есть ссылка с именем 'o2'. ВОПРОС 2: Это новая ссылка, которая добавляется и живет в стеке и ссылается на ссылку «object2»? Или «o2» просто псевдоним, поддерживаемый в коде (а не в памяти), и на самом деле в памяти все еще есть только одна ссылка на «Браво», называемая «object2», и когда этот код фактически выполняется, «o2.foo» обрабатывается как «object2.foo»?

А теперь мы подошли к самой сложной части вашего вопроса. o2 — это ссылка другого рода. Это не ссылка на объект в куче, а фактически псевдоним (как вы предполагаете) поля object2 в объекте Foo. Однако o2 по-прежнему занимает место в краткосрочном хранилище, поскольку он по-прежнему является аргументом метода.

Кроме того, тот факт, что в памяти есть только одна ссылка на Bravo, вас не должен волновать. Ссылки, которые доступны из известных корней GC, определяют, можно ли безопасно собрать конкретный объект.

person dlev    schedule 28.02.2012