Есть ли способ найти свойства объекта в списке <T>, используя Contains? - PullRequest
0 голосов
/ 05 августа 2009

Я бродил, как я могу узнать, существует ли объект в моем списке. Я добавляю «newPerson» (экземпляр класса Person) в список, но проверяю, существует ли содержимое / свойства newPerson в списке.

Этот кусок отлично работает:

        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;
        }

Прежде всего, я хотел упростить / оптимизировать этот уродливый код выше. Поэтому я подумал об использовании метода 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;
        }

Второй код выше не работает, я думаю, что он сравнивает ссылки на объекты, а не содержимое / свойства объекта.

Кто-то здесь в Stackoverflow и в тексте ссылки говорил об использовании класса, реализующего IEqualityComparer. Я попробовал, но теперь код стал намного больше! Что-то вроде:

    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;
    }

}

и использовать этот компаратор:

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

Есть ли меньший способ найти свойства моего объекта в списке?

Ответы [ 2 ]

3 голосов
/ 05 августа 2009

Похоже, ваш класс Person должен реализовывать IEquatable . Да, это (немного) больше кода, но тогда вам не нужно повторять его каждый раз, когда вы хотите сравнить объекты двух человек.

Метод списка содержит метод Equals объекта по умолчанию. Поэтому, если вы правильно внедрили IEquatable, вам не нужно передавать пользовательский IEqualityComparer.

1 голос
/ 05 августа 2009

Используйте Exists или Any с предикатом:

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;
}

Это будет работать с .NET 2.0 (и может быть преобразовано в C # 2 с помощью анонимного метода). Более 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;
}
...