¿Hay alguna manera de encontrar las propiedades de un objeto en List < T > utilizando contiene?

StackOverflow https://stackoverflow.com/questions/1235370

Pregunta

Estaba deambulando, ¿cómo puedo saber si un objeto ya existe en mi Lista? Estoy agregando " newPerson " (instancia de la clase Persona) en una Lista, pero comprobando si los contenidos / propiedades de newPerson existen o no en la Lista.

Esta pieza funciona bien:

        List<Person> people = this.GetPeople();
        if (people.Find(p => p.PersonID  == newPerson.PersonID
                    && p.PersonName  == newPerson.PersonName) != null)
        {
            MessageBox.Show("This person is already in the party!");
            return;
        }

En primer lugar, quería simplificar / optimizar este código feo anterior. Entonces pensé en usar el método Contains.

        List<Person> people = this.GetPeople();
        if (people.Contains<Person>(newPerson)) //it doesn't work!
        {
            MessageBox.Show("This person is already in the party!");
            return;
        }

El segundo código anterior no funciona, creo que está comparando referencias de objetos y no contenidos / propiedades del objeto.

Alguien aquí en Stackoverflow y en texto del enlace estaba hablando de usar una clase que implementa IEqualityComparer. Lo intenté, ¡pero el código es mucho más grande ahora! Algo así como:

    public class PersonComparer : IEqualityComparer<Person>
    {
    // Products are equal if their names and i numbers are equal.
    public bool Equals(Person x, Person y)
    {

        // Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        // Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        // Check whether the products' properties are equal.
        return x.PersonID == y.PersonID && x.PersonName == y. PersonName;
    }

    // If Equals() returns true for a pair of objects,
    // GetHashCode must return the same value for these objects.

    public int GetHashCode(Person p)
    {
        // Check whether the object is null.
        if (Object.ReferenceEquals(p, null)) return 0;

        // Get the hash code for the Name field if it is not null.
        int hashPersonName = p.PersonName == null ? 0 : p.PersonName.GetHashCode();
        int hashPersonID = i.PersonID.GetHashCode();

        // Calculate the hash code for the i.
        return hashPersonName ^ hashPersonID;
    }

}

y para usar este comparador:

        PersonComparer comparer = new PersonComparer();
        if (people.Contains<Person>(newPerson, comparer))
        {
            MessageBox.Show("This person is already in the party.");
            return;
        }

¿Hay una forma más pequeña de encontrar las propiedades de mi objeto en una Lista?

¿Fue útil?

Solución

Utilice Existe o Cualquiera con un predicado:

List<Person> people = this.GetPeople();
if (people.Exists(p => p.PersonID  == newPerson.PersonID
                       && p.PersonName  == newPerson.PersonName))
{  
    MessageBox.Show("This person is already in the party!");
    return;
}

Eso funcionará con .NET 2.0 (y se puede convertir a C # 2 usando un método anónimo). La solución más LINQy es Any :

List<Person> people = this.GetPeople();
if (people.Any(p => p.PersonID  == newPerson.PersonID
                    && p.PersonName  == newPerson.PersonName))
{
    MessageBox.Show("This person is already in the party!");
    return;
}

Otros consejos

Parece que su clase Person debería implementar IEquatable < Person > . Sí, es (un poco) más de código, pero no tiene que repetirlo cada vez que quiera comparar objetos de 2 personas.

El método Contains de la lista usa el método Equals del objeto por defecto. Entonces, si implementa IEquatable correctamente, no tiene que pasar un IEqualityComparer personalizado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top