none
Objetos y Listas Genericas RRS feed

  • Pregunta

  • A ver.... les pongo el codigo y abajo les planteo el problema:

    [CODIGO DE UN WINFORM CON UN BUTTON1]

     

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

     

    namespace WindowsFormsApplication1

    {

          public partial class Form1 : Form

          {

                public Form1()

                {

                      InitializeComponent();

                }

     

                private void button1_Click(object sender, EventArgs e)

                {

                      List<contenedor> Lista = generar_lista();

     

                      Console.Write("listo!");

                }

     

                private List<contenedor> generar_lista()

                {

     

                      List<contenedor> contenedores = new List<contenedor>();

                      contenedor oC = null;

                      contenida oc = null;

     

                      try

                      {

     

                            for (int i = 0; i < 1; i++)

                            {

     

                                  oC = new contenedor();

                                  oC.imiembro = i;

                                  oC.smiembro = "hola";

                                  oC.omiembro = new Form1();

     

                                  oc = new contenida();

                                  oc.imiembro = i * 2;

                                  oc.smiembro = "chau";

                                  oc.omiembro = button1;

     

                                  oC.ContenidaMiembro = oc;

     

                                  contenedores.Add(oC);

                            }

     

                      }

                      catch

                      {

     

                      }

                      finally

                      {

     

                            oC.Dispose();

                            oC = null;

     

     

                      }

     

                      return contenedores;

                }

     

          }

     

          class contenedor : IDisposable

          {

     

                public int imiembro;

                public string smiembro;

                public object omiembro;

                public contenida ContenidaMiembro;

     

                #region Miembros de IDisposable

     

                public void Dispose()

                {

                      ContenidaMiembro = null;

                }

     

                #endregion

          }

     

          class contenida

          {

     

                public int imiembro;

                public string smiembro;

                public object omiembro;

     

          }

    }

     


    [EXPLICACION]

    La onda viene siendo, cuando estoy en la funcion Cargar_Lista() me veo forzado a crear un Objeto tipo Contenedora para poder agregarlo a la lista... y ahi me pongo a pensar: "luego de agregar el objeto contenedora, no seria bueno eliminarlo?" - lo primero que pense es que al hacerle dispose (para no esperar q el GC me lo destruya cuando quiera, y sí ya se q no hay un destructor definido, pero obvien eso...) al objeto Contenedora deberia destruirse tanto el objeto q cree como la REFERENCIA q agregue a la lista generica....
    pero estaba equivocado... si uds debuguean el codigo, van a ver q al hacer el dispose se destruye el objeto q cree, PERO EL DE DENTRO DE LA LISTA SE MANTIENE VIVO!!!! - no solo eso sino que el objeto externo a la lista y el contenido en la misma TIENEN EL MISMO HASHCODE!!!! - y la cereza de la torta es: el objeto Contenedora, contiene como miembro un objeto Contenida, cuando hago el Dispose del Contenedora externo a la lista, el Contenedora interno de la lista PIERDE LA REFERENCIA AL OBJETO CONTENIDA!!!

    De todo esto, mi planteo son los siguientes:
    1- El metodo .Add() de las listas genericas, agrega una copia POR VALOR del objeto q estoy pasando ? (o sea, copia el estado del objeto)
    2- por que cuernos el miembro Contenida se vuelve null mientras q el Contenedora sigue vivo dentro de la lista?
    3- Que recomendacion hay acerca de, en estos casos, liberar los objetos q uno crea para agregar en la lista?
    Es recomedable liberar por uno mismo los objetos q se agregan a la lista ? si no hiciera el dispose en Cargar_Lista quien destruiria al objero Contenedora (si es q alguna vez se destruye) el GC tal vez?

    Son muchas preguntas, lo se... pero realmente me resulta muy raro este comportamiento... agradecere su tiempo!

    Saludos y gracias!
    JP

     

    jueves, 17 de diciembre de 2009 13:05

Respuestas

  • 1) El metodo add agrega una referencia (y no una copia por valor). Para comprobarlo puedes crear un objeto, agregarlo a la lista, modificar el objeto y ver que se modifica en ambos lados (fuera y dentro de la lista), porque son en realidad el mismo objeto.

    2) Contenida se vuelve null porque el dispose la vuelve null, pero el contenedor sigue "vivo" hasta que el GC lo requiera. El dispose simplemente indica que dicho objeto se puede eliminar, pero no lo elimina en ese momento. De hecho solo marca esa porcion de memoria como utilizable y llegado el caso, podra asignarla a otro objeto. Mientras tanto sigue alli... y es por eso que aun lo puedes ver. Eso si, luego del dispose no deberias utilizar el objeto liberado.

    3) Los objetos que agregues a la lista no debes liberarlos hasta tanto estes seguro que no lo vas a utilizar mas. En el caso de las listas y de objetos que no usen muchos recursos, lo mejor es dejar que al quedar fuera de scope se destruyan solos. Por ejemplo si la lista la declaras como miembro de un form, al hacerse el dispose del form, la lista queda fuera de scope y el GC se va a encargar de eliminar sus elementos.

     

    Espero haber sido, claro. Cualquier cosa, vuelve a preguntar.

    • Marcado como respuesta JPSharp viernes, 17 de diciembre de 2010 16:38
    jueves, 2 de diciembre de 2010 23:04