none
Comparar dos objetos de la misma clase para saber si sus instancias son iguales RRS feed

  • Pregunta

  • Buenas noches:

    Estoy trabajando en una aplicación para guardar objetos en bd, y tengo una inquietud:

    Si tengo una clase , por ejemplo Persona, y quiero hacer una actualización a x Persona, existe en C# alguna forma para saber si la persona previa ha cambiado? Quiero hacer Persona tPersona que carga los datos actuales de una base de datos, de la persona consultada, los carga en textbox, y Persona uPersona, que cargará los datos de los textbox. Requiero saber si tPersona = uPersona, es decir si las propiedades de tPersona y uPersona son iguales, con lo cual sabre que no hubo cambios y si por el contrario tPersona != uPersona será claro que hubo cambios; esto me permitirá  no sólo realizar la actualización sino también determinar si hay que guardar datos cuando el evento formclosing sea lanzado o cuando quiera cerra la aplicación.

    Mil gracias



    C# para todos




    • Editado caliche68 martes, 12 de diciembre de 2017 0:57
    lunes, 11 de diciembre de 2017 1:00

Respuestas

  • hola

    >>Quiero hacer Persona tPersona que carga los datos actuales de la persona consultada, y Persona uPersona, que cargará los datos de los textboxes del formulario

    la forma de saber si hay cambios es poe medio de un hash de la informacion, o sea no necesitas dos instancia de persona y compara

    sino que asignas los datos a tPersona y generas un hash de la informacion y lo mentienes, luego a esta misma tPersona le vuelcas los datos de los textbox y generas el nuevo hash si difieren entonces hay cambios

    si los datos se mentienen quiere decir que son iguales a los que ya tenias

    How to generate a unique hash code for an object, based on its contents?

    Generate hash of object consistently

    hay varias formas de obtener el hash, se podria usar el

    Object.GetHashCode Method

    o se podria serializar a json el objeto y sobre el string aplicar el ComputeHash, para mi lo del json es lo mas simple, entonces no necesitas dos objetos diferentes que comparar, sino que es el mismo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 11 de diciembre de 2017 10:20

Todas las respuestas

  • Si es posible, para ello debes de implementar la interfaz IEquatable<T> en la clase, por ejemplo:

    - Clase Persona

    public class Persona : IEquatable<Persona>
    {
    	public int id { get; set; }
    	public string Nombre { get; set; }
    
    	public Persona(int id, string Nombre)
    	{
    		this.id = id;
    		this.Nombre = Nombre;
    	}
    
    	public override bool Equals(object obj)
    	{
    		var _persona = obj as Persona;
    
    		if (_persona == null) return false;
    
    		return Equals(_persona);
    	}
    
    	public override int GetHashCode()
    	{
    		return this.id.GetHashCode()
    				^ this.Nombre.GetHashCode();
    	}
    
    	public bool Equals(Persona _persona)
    	{                
    		//¿Se trata de la misma instancia?
    		if (ReferenceEquals(this, _persona)) return true;
    		
    		//Realizar comparaciones
    		if (this.id.CompareTo(_persona.id) != 0) return false;
    		if (!this.Nombre.Equals(_persona.Nombre)) return false;
    		
    		return true;
    	}
    }

    - Probando...

    var p1 = new Persona(1, "Mario Salas");
    var p2 = new Persona(1, "Mario Salas");
    
    bool result1 = p1.Equals(p2);
    //Result: true
    
    var p3 = new Persona(2, "Luis Salinas");
    bool result2 = p1.Equals(p3);
    //Result: false
    
    var p4 = p3; 
    bool result3 = p3.Equals(p4);
    //Result: true


    • Propuesto como respuesta Jorge TurradoMVP lunes, 11 de diciembre de 2017 12:04
    lunes, 11 de diciembre de 2017 2:51
  • hola

    >>Quiero hacer Persona tPersona que carga los datos actuales de la persona consultada, y Persona uPersona, que cargará los datos de los textboxes del formulario

    la forma de saber si hay cambios es poe medio de un hash de la informacion, o sea no necesitas dos instancia de persona y compara

    sino que asignas los datos a tPersona y generas un hash de la informacion y lo mentienes, luego a esta misma tPersona le vuelcas los datos de los textbox y generas el nuevo hash si difieren entonces hay cambios

    si los datos se mentienen quiere decir que son iguales a los que ya tenias

    How to generate a unique hash code for an object, based on its contents?

    Generate hash of object consistently

    hay varias formas de obtener el hash, se podria usar el

    Object.GetHashCode Method

    o se podria serializar a json el objeto y sobre el string aplicar el ComputeHash, para mi lo del json es lo mas simple, entonces no necesitas dos objetos diferentes que comparar, sino que es el mismo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 11 de diciembre de 2017 10:20
  • Buenas tardes Juan Mondragón:

    Me parece genial tu propuesta, pero en verdad, sé poco sobre hashcode, y pues para que veas lo que he estado haciendo te envio mi codigo... Te agradezco cualquier ayuda respecto de tu propuesta.

    public class Cliente: IEquatable<Cliente>

        {

            private string cedula;
             // Propiedades del objeto

            public string Nombres { get; set ; }
            public string Apellidos { get ; set ; }
            public string Direccion { get; set; }
            public string Telefono1 { get; set; }
            public string Telefono2 { get; set  ; }
            public string Correo { get; set; }
            public string Cedula { get => cedula; set
                {
                    if (String.IsNullOrEmpty(value))
                        throw new ArgumentException("La cédula no puede ser nula o vacía.");
                    else
                        this.cedula = value;
                }
            }
            public string Cargo { get; set ; }
            public string NombreEmpresa { get; set ; }

            public bool Equals(Cliente alter)
            {
                if (alter == null)
                    return false;

                return
                    string.Equals(this.Nombres, alter.Nombres) &&
                    string.Equals(this.Apellidos, alter.Apellidos) &&
                    string.Equals(this.Direccion, alter.Direccion) &&
                    string.Equals(this.Telefono1,alter.Telefono1) &&
                    string.Equals(this.Telefono2,alter.Telefono2) &&
                    string.Equals(this.Correo,alter.Correo) &&
                    string.Equals(this.Cedula,alter.Cedula) &&
                    string.Equals(this.Cargo,alter.Cargo) &&
                    string.Equals(this.NombreEmpresa,alter.NombreEmpresa);
                
            }
            public override bool Equals(object obj)
            {
                if (obj is null) return false;
                if (ReferenceEquals(this, obj)) return true;
                if (obj.GetType() != GetType()) return false;
                return Equals(obj as Cliente);
            }
            public static bool operator ==(Cliente c1, Cliente c2)
            {
                if ((object)c1 == null || ((object)c2) == null)
                    return Object.Equals(c1, c2);

                return c1.Equals(c2);
            }
            public override int GetHashCode()
            {
                return this.Cedula.GetHashCode();
            }
            public static bool operator !=(Cliente c1, Cliente c2)
            {
                if (c1 == null || c2 == null)
                    return !Object.Equals(c1, c2);

                return !(c1.Equals(c2));
            }
        }


    C# para todos

    lunes, 11 de diciembre de 2017 19:09
  • Buenas tardes Juan Mondragón:

    Con este código me está funcionando, pero como dices es más eficiente si uso un sólo objeto en lugar de dos.

    Me podrías ejemplificar


    C# para todos

    martes, 12 de diciembre de 2017 1:56
  • Hola caliche68,

    Creo que hubo una confusión, la persona que te respondió fue Leandro Tuttini, yo solamente la propuse como una posible respuesta.

    Todos los créditos son de él.

    Gracias por usar los foros de MSDN.

    Juan
     _____

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde. 

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.  

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft.

    miércoles, 13 de diciembre de 2017 17:22
    Moderador