2012-02-28 4 views
1

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

Давайте предположим, что следующий код ...

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; 
     } 

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

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

ответ

1

Я понимаю, что при // POINT A - вы создали четыре экземпляра MyObject для . Эти четыре экземпляра живут в куче.

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

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

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

Я понимаю, что при // POINT B - вы создали новую ссылку на 'Alpha' с именем 'o1'. Эта ссылка добавляется и живет в стеке. Когда метод возвращается, эта ссылка удаляется.

Да, в точке В, параметр o1 также сохраняет ссылку на MrObject, который был передан в качестве аргумента. o1 живет в краткосрочном магазине, который, в общем, будет «стеком». Когда метод закончится, пространство в кратковременном хранилище, используемое для o1, станет доступным для другого использования, и сборщик мусора больше не будет рассматривать o1 как известный живой корень.

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

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

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

+0

Отличный ответ - спасибо! – chopperdave

Смежные вопросы