2015-11-13 3 views
0

Здесь приведен пример кода в Windows Forms:Видимость внутри класса объектов создаются локально

namespace WindowsFormsApplication1 
{ 
    public class contained 
    { 
     public int value; 
    } 

    public class container 
    { 
     public List<contained> c1 = new List<contained>(); 

     public void add_contained() 
     { 
      contained tmp = new contained(); 
      tmp.value = 1; // some default value 
      c1.Add(tmp); 
     } 
    } 

    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      container cnt = new container(); 
      cnt.add_contained(); 
      int i = cnt.c1[0].value; // this works, why? 
     } 
    } 
} 

Практически, у меня есть большой класс «контейнер», который управляет список сложных объектов «содержащийся». Существует процедура добавления нового пустого объекта в список - для последующего изменения. Теперь я выполнил код выше, и он работает, но я не понимаю, почему.

Если процедура «add_contained» для добавления объекта по умолчанию в список создает локально, я ожидаю, что он исчезнет, ​​когда процедура завершится, поэтому список должен оставаться с нулевым указателем. Вместо этого я могу получить доступ к объекту в списке, как указано в последней строке «int i = ...».

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

Каков правильный способ решения проблемы, изложенной в приведенном выше коде? Благодарю.

+0

вы добавили его в коллекцию, чтобы по-прежнему ссылаться на нее. в чем проблема? – Plutonix

ответ

2

Когда вы делаете new contained(), новый объект создается и хранится «где-то».
Затем ссылка на него присваивается tmp.
Эта же ссылка, в свою очередь, добавлена ​​в список и вы выходите из метода.
В этот момент переменная tmp «уничтожена», но объект все еще находится в памяти (поскольку он по-прежнему ссылается через список).

Если в какой-то момент вы удалите элемент списка, ссылку на этот объект; и нет других ссылок на этот объект; он становится пригодным для сбора, то есть GC может освободить его память.

+0

Я думаю, что у меня есть проблеск непонятного, или, по крайней мере, я вижу, что механизм может работать. Короче говоря, локальная переменная внутри процедуры обрабатывается отдельно от объекта, созданного с помощью «новой» инструкции. Таким образом, этот объект, плавающий в памяти, до завершения процедуры, имеет 2 ссылки, один локальный и один глобальный, и только когда локаль уничтожается, когда процедура заканчивается. Поэтому я должен забыть область видимости для объектов и вместо этого подсчитать ссылки. –

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