Existe uma maneira de encontrar propriedades de um objeto em List usando Contém?
-
22-07-2019 - |
Pergunta
Eu estava vagando como posso descobrir se um objeto já existe na minha lista. Eu estou adicionando "newPerson" (instância da classe Person) em uma lista, mas verificar se o conteúdo newPerson / propriedades existe ou não na lista.
Esta peça funciona bem:
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;
}
Em primeiro lugar, eu queria para simplificar / otimizar esse código feio acima. Então eu pensei sobre o uso do método Contém.
List<Person> people = this.GetPeople();
if (people.Contains<Person>(newPerson)) //it doesn't work!
{
MessageBox.Show("This person is already in the party!");
return;
}
O segundo código acima não funciona, eu acho que ele está comparando referências objetos e não o conteúdo de objetos / propriedades.
Alguém aqui na Stackoverflow e em texto do link estava falando sobre o uso de uma classe que implementa IEqualityComparer. Eu dei-lhe uma tentativa, mas o código é muito maior agora! Algo 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;
}
}
e usar este comparer:
PersonComparer comparer = new PersonComparer();
if (people.Contains<Person>(newPerson, comparer))
{
MessageBox.Show("This person is already in the party.");
return;
}
Existe uma maneira pequena para encontrar propriedades de meu objeto em uma lista?
Solução
Use Exists
ou Any
com um 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;
}
Esse trabalho vontade com .NET 2.0 (e pode ser convertido em C # 2 utilizando um método anônimo). A solução mais LINQy é 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;
}
Outras dicas
Parece que a sua classe Person deve implementar IEquatable
A Contém método da lista usa o método do objeto por padrão é igual. Então, se você implementar IEquatable corretamente, você não tem que passar por um IEqualityComparer personalizado.