none
Porque no se puede copiar Objetos. RRS feed

  • Pregunta

  • hola, les comento tengo dos formularios donde se ha pasado como referencia un objeto, en el form hijo tengo una lista de objetos con data.

    Form padre: .... frmClientes = new Frm_ListaPersonas(ref epersona) ... Form hijo: Aqui tengo una lista de objetos. EPersona epersona; List<EPersona> listPersona = new List<EPersona>(); public Frm_ListaPersonas(ref EPersona epersona) { InitializeComponent(); this.epersona = epersona;

    .... } public void seleccion(){ ... epersona= (from p in listPersona where p.Id ==3 select p).FirstOrDefault() ... }


    En el form hijo si se asigno los datos aparentemente si hizo la copia, sin embargo en el form padre el objeto  pasado por referencia esta en null..

    Pero si en el Form hijo hago un --> epersona.nombre="Carlitos" en el form padre si se ve el cambio en dicho campo.

    Una manito para entender la lógica de esto.

    • Editado Novatoj sábado, 30 de junio de 2018 23:12
    sábado, 30 de junio de 2018 23:10

Respuestas

  • Hola Novatoj:

    Al declarar en el form hijo un objeto que se llama epersona (Epersona epersona;), no es el mismo objeto que le pasas por referencia, en el sitio de la memoria donde se crean las variables, has inicializado una nueva variable.

    A la misma le asignas el "contenido" de la variable que pasas por referencia, por tanto estas hablando de dos variables diferentes. Qué disponen de una dirección de memoria donde están las propiedades de persona (esto si es los mismos valores)

    this.epersona = variable epersona del objeto Formulario hijo. Cuando formhijo se cierra, variable se destruye. (pero los valores persisten, por eso formpadre tiene valor)

    Un ejemplo, que supongo te ayudará a comprenderlo.

    class Persona
        {
            public string nombre { get; set; }
            public string apellido { get; set; }
    
            public override string ToString()
            {   
     	        return "La persona se llama : "+this.nombre + " - "+this.apellido;
            }
        }
    
      class Program
        {
            static void Main(string[] args)
            {
                Persona p = new Persona();
                p.nombre = "juan";
                p.apellido = "garcia";
    
                /* objeto p tiene contenido */
    
                Persona p2 = p;
                Console.Out.WriteLine("persona p: "+p.ToString());
                Console.Out.WriteLine("persona p2: " + p2.ToString());
                /*aparentemente p2 tiene lo mismo que p */
    
                p2.apellido = "fernández";
    
                /*al cambiar el contenido de p2, como su referencia de memoria apunta al mismo sitio en la zona donde estan los valores
                 * que su objeto p los dos cambian porque acceden al mismo sitio 
                 */
                Console.Out.WriteLine("persona p: " + p.ToString());
                Console.Out.WriteLine("persona p2: " + p2.ToString());
    
                p2 = null;
    
                Console.Out.WriteLine("persona p: " + p.ToString());
                
                /* aun cuando he asignado p2 como nulo, p mantiene su valor.*/
    
                Console.ReadLine();
            }
        }

    Un saludo

    • Marcado como respuesta Novatoj lunes, 2 de julio de 2018 15:08
    domingo, 1 de julio de 2018 6:41

Todas las respuestas

  • Hola Novatoj:

    Al declarar en el form hijo un objeto que se llama epersona (Epersona epersona;), no es el mismo objeto que le pasas por referencia, en el sitio de la memoria donde se crean las variables, has inicializado una nueva variable.

    A la misma le asignas el "contenido" de la variable que pasas por referencia, por tanto estas hablando de dos variables diferentes. Qué disponen de una dirección de memoria donde están las propiedades de persona (esto si es los mismos valores)

    this.epersona = variable epersona del objeto Formulario hijo. Cuando formhijo se cierra, variable se destruye. (pero los valores persisten, por eso formpadre tiene valor)

    Un ejemplo, que supongo te ayudará a comprenderlo.

    class Persona
        {
            public string nombre { get; set; }
            public string apellido { get; set; }
    
            public override string ToString()
            {   
     	        return "La persona se llama : "+this.nombre + " - "+this.apellido;
            }
        }
    
      class Program
        {
            static void Main(string[] args)
            {
                Persona p = new Persona();
                p.nombre = "juan";
                p.apellido = "garcia";
    
                /* objeto p tiene contenido */
    
                Persona p2 = p;
                Console.Out.WriteLine("persona p: "+p.ToString());
                Console.Out.WriteLine("persona p2: " + p2.ToString());
                /*aparentemente p2 tiene lo mismo que p */
    
                p2.apellido = "fernández";
    
                /*al cambiar el contenido de p2, como su referencia de memoria apunta al mismo sitio en la zona donde estan los valores
                 * que su objeto p los dos cambian porque acceden al mismo sitio 
                 */
                Console.Out.WriteLine("persona p: " + p.ToString());
                Console.Out.WriteLine("persona p2: " + p2.ToString());
    
                p2 = null;
    
                Console.Out.WriteLine("persona p: " + p.ToString());
                
                /* aun cuando he asignado p2 como nulo, p mantiene su valor.*/
    
                Console.ReadLine();
            }
        }

    Un saludo

    • Marcado como respuesta Novatoj lunes, 2 de julio de 2018 15:08
    domingo, 1 de julio de 2018 6:41
  • Hola de nuevo:

    Un apunte interesante y bien documentado lo tienes aquí.

    https://geeks.ms/etomas/2012/04/23/c-bsico-paso-por-referencia/

    Un saludo

    domingo, 1 de julio de 2018 6:52
  • hola

    Cuendo pasas objetos entre formularios NUNCA lo haces por referencia porque esto genera ocoplamientos, y es algo que justamente intentas evitar cuando programas orientado a objetos

    es correcto como pasas la lista en el constructor del form hijo, pero quita el ref

    cuando termines de trabajar la lista, pasala a la instancia del forma padre ya modificada

    Comunicar Formularios

    en el articulo explico como pasando la insterfaz podrias comunicar formsde forma desacoplada, pasando objetos de uno a otro

    >>Pero si en el Form hijo hago un --> epersona.nombre="Carlitos" en el form padre si se ve el cambio en dicho campo.

    eso no tiene sentido, valida que el linq este retornando un item, porque el FirstOrDefault() sino encuentra nada retorna null

    mas alla que pongas el ref o no para objetos siempre se pasan por referencia, si quitas el ref es lo mismo

    >>sin embargo en el form padre el objeto  pasado por referencia esta en null..

    pero en que momento evaluas el valor de las variables, porque hasta tanto no hayas pasado por selecion() no tendras nada que evaluar

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 2 de julio de 2018 4:55
  • hola, 

    ">>Pero si en el Form hijo hago un --> epersona.nombre="Carlitos" en el form padre si se ve el cambio en dicho campo.

    eso no tiene sentido, valida que el linq este retornando un item, porque el FirstOrDefault() sino encuentra nada retorna null"

     al hacer..  epersona.nombre="Carlitos" lo hago a modo de test no considero la consulta con linq para ver si en el form padre se le ha asignado dicho valor en el Campo Nombre.

    ////// Form Hijo.... 
    
    EPersona epersona;
    List<EPersona> listPersona = new List<EPersona>();
    public Frm_ListaPersonas(ref EPersona epersona)
    {
       InitializeComponent();
       this.epersona = epersona;
       listPersona=cn.listarPersonas();
       ....
    }
    
    public void seleccion(){
    ...
      // epersona= (from p in listPersona where p.Id ==3 select p).FirstOrDefault()
    epersona.Nombre="Carlitos";
    ...
    }
    
    

    De esta forma en el form Padre si camptura el cambio, pero yo deseo que todo el objeto sea capturado ( por ello linq)... 

    >>sin embargo en el form padre el objeto  pasado por referencia esta en null..

    pero en que momento evaluas el valor de las variables, porque hasta tanto no hayas pasado por selecion() no tendras nada que evaluar

    Lo evaluo despues de pasar por el metodo seleccion() usando el debug... Creo que es un tema de direccion de memoria... revisare el link que sugirio..  ya le comento el desenlace .. :).. 

    lunes, 2 de julio de 2018 14:59
  • Esto problemas suelen ser muy fácil de entender lo que está mal cuando se tiene el código y se sabe con precisión el orden de ejecución. Tal vez tendrías que copiar el código de los dos formularios (aunque le borres todo lo que no viene al caso), pero que quede claro la definición de cada form, desde donde se los llama y donde se definen las variables. Indica donde pones el punto de interrupción y el valor obtenido.
    • Editado AntiWork lunes, 2 de julio de 2018 19:32
    lunes, 2 de julio de 2018 19:29