Есть ли способ найти свойства объекта в List‹T› с помощью Contains?

Я блуждал, как я могу узнать, существует ли объект в моем списке. Я добавляю «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;
        }

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


person Junior Mayhé    schedule 05.08.2009    source источник
comment
Следует пометить его .net и С#   -  person jpbochi    schedule 06.08.2009


Ответы (2)


Используйте 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;
}
person Jon Skeet    schedule 05.08.2009
comment
Да, я попробую! Спасибо, Джон! - person Junior Mayhé; 12.08.2009

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

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

person driis    schedule 05.08.2009