entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Copiar lista genérica [C#]

Tengo un listado genérico:

List<TareaOSBO> listTareas= new List<TareaOSBO>();

el cual después de aplicarle un par de filtros me devuelve un solo item de dicho listado: lo que quiero es duplicar dicho item, y volverlo añadir al listado es decir:

tengo mi item1, lo copio item1-->copiaitem1, modifico la copia, y luego lo vuelvo añadir, copiaitem1 --> tareaExistente.add(copiaitem1). El problema es que cuando modifico la copia, se me esta modificando también el original y no se porque, ya intente pasarlo a un nuevo listado, de esta forma:

private void CargarDetTareasRepetidas(List<TareaOSBO> tareaExistente)
{
   List<TareaOSBO> copiaTarExistente = new List<TareaOSBO>();        
   copiarTarExistente = tareaExistente;

  //A partir de aquí modifico copiarTarExistente 
  foreach (TareaOSBO itemT in copiaTarExistente)
     {                    
        itemT.AplicaTiempo = false;
        itemT.IdFallaOS = idFallaOS;
        itemT.IdTareaOS = idTareaOS;        
        listTareas.Add(itemT);
      }
}

No se de que otra forma hacer que me modifique solo la copia para que no me modifique el original y al añadirlo de nuevo al listado sean diferentes.

bl4z3r comentado Feb 24, 2016

¿Para que finalidad necesitas hacer esto? Es posible que pueda recurrir a otra solución.

Andhii1293 comentado Feb 24, 2016

Necesito duplicar un elemento de la lista de tareas (tareaexistente) y modificarle solo algunas cosas (aplicatiempo,idfallaOSy idTareaOS), el resto queda igual, y luego volver a añadirlo a la lista de tareas. de esta manera tendré dos tareas "casi" iguales con ciertas características cambiadas.

4 Respuestas

4votos

bl4z3r Puntos16340

Despues de investigar un poco, la solución esta en usar el método que heredan todos los objetos: MemberwiseClone()

Aca te dejo el codigo que use para ejemplificar:

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        List<TareaOSBO> lista = new List<TareaOSBO>()
            {
                new TareaOSBO() { AplicaTiempo = true, IdFallaOs = 1, IdTareaOs = 6 },
                new TareaOSBO() { AplicaTiempo = true, IdFallaOs = 2, IdTareaOs = 5 },
                new TareaOSBO() { AplicaTiempo = true, IdFallaOs = 3, IdTareaOs = 4 },
                new TareaOSBO() { AplicaTiempo = true, IdFallaOs = 4, IdTareaOs = 3 },
                new TareaOSBO() { AplicaTiempo = true, IdFallaOs = 5, IdTareaOs = 2 },
                new TareaOSBO() { AplicaTiempo = true, IdFallaOs = 6, IdTareaOs = 1 }
            };

        lista.ForEach(x => Console.WriteLine("Antes: {0} - {1} - {2}", x.AplicaTiempo, x.IdFallaOs, x.IdTareaOs));

        var tareaModificada = lista.Single(x => x.IdFallaOs == 1).ShallowCopy();
        tareaModificada.AplicaTiempo = false;
        tareaModificada.IdTareaOs = 10;

        lista.Add(tareaModificada);

        lista.ForEach(x => Console.WriteLine("Despues: {0} - {1} - {2}", x.AplicaTiempo, x.IdFallaOs, x.IdTareaOs));
    }
}

public class TareaOSBO
{
    public bool AplicaTiempo { get; set; }
    public int IdFallaOs { get; set; }
    public int IdTareaOs { get; set; }

    public TareaOSBO ShallowCopy()
    {
       return (TareaOSBO)MemberwiseClone();
    }
}

Dando como resultado lo siguente:

Antes: True - 1 - 6
Antes: True - 2 - 5
Antes: True - 3 - 4
Antes: True - 4 - 3
Antes: True - 5 - 2
Antes: True - 6 - 1
Despues: True - 1 - 6
Despues: True - 2 - 5
Despues: True - 3 - 4
Despues: True - 4 - 3
Despues: True - 5 - 2
Despues: True - 6 - 1
Despues: False - 1 - 10

Y el demo del mismo esta acá: dotnetfiddle

Andhii1293 comentado Feb 25, 2016

Aplique este método y me funciono, muchísimas gracias por tomarte el tiempo para explicarlo.

Saludos!

bl4z3r comentado Feb 25, 2016

@Andhii1293 De nada, para eso estamos.

2votos

cobasESP Puntos19020

Hola, la hacer itemoriginal = itemcopado, estas creando un espacio en la memoria que apunta a item original, si este cambia lo hará tambien el otro, prueba esto:

TareaOSBO itemoriginal = copiatTarExistente.get(0); //Guarda un solo item de la lista

//Ahora en vez de hacer un puntero, creo un objeto nuevo y le vuelco el valor del otro
TareaOSBO itemrepetido = new TareaOSBO();
itemrepetido = itemoriginal;

De esta manera la crear un item nuevo, este no apunta a la posicion de memoria que tiene el primero, sino que se crea una distinta y ya, después de esto vuelco los datos en él.

4votos

carlossevi Puntos58680

Lo que quieres es hacer un clon o "copia profunda" del objeto. Para eso se utiliza el método Clone() de los objetos. Como comentan en este completo hilo de Stackoverflow lo que hace el método es serializar el objeto para deserializarlo en un objeto nuevo, pero necesita que la clase sea serializable. En el enlace anterior puedes encontrar toda la información.

Otra opción que creo que puede funcionar es crear un método que devuelve una nueva instancia de la clase:

public class Person
{
    // Atributos
    public string name;

    // Constructor con un argumento
    public Person(string nm)
    {
        name = nm;
    }

    // Método para clonar
    public Person Clonar()
    {
        return new Person(this.name);
    }
}

0voto

Lo que implemento para hacer copiar de objetos es la interface ICloneable que permite clonar los objetos sin apuntar al mismo espacio de memoria.

https://msdn.microsoft.com/en-us/library/system.icloneable(v=vs.110).aspx

Saludos.

Por favor, accede o regístrate para responder a esta pregunta.

¿Conoces alguien que puede responder?
¡Comparte esta pregunta!


Actividad Reciente

¿Eres Usuario Apple?

...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta