C # Список дубликатов - PullRequest
       3

C # Список дубликатов

3 голосов
/ 29 марта 2012

Мне интересно, почему, когда я пытаюсь не добавлять свой объект в список, когда он дублируется, он все равно добавляет его

if (thePreviousList.Contains(thePreviousItem))
{
}
else
{
    thePreviousList.Add(thePreviousItem);
}

Например, thepreviousitem id = 1 и name = test И если у меня есть другой объектс тем же идентификатором и тем же именем он все равно добавит его ...

Ответы [ 5 ]

5 голосов
/ 29 марта 2012

Вам необходимо правильно реализовать метод Equals для объекта, который вы пытаетесь добавить в список.Чтобы определить, содержит ли список уже переданный объект, метод Contains использует Equals.

4 голосов
/ 29 марта 2012

Если вы не хотите переопределять Equals, вы можете использовать LINQ, чтобы проверить, существует ли уже объект с таким же идентификатором и именем (что необязательно тот же объект ):

if (thePreviousList.Any(item => item.ID == thePreviousItem.ID
                             && item.Name == thePreviousItem.Name)) 
{ 
} 
else 
{ 
    thePreviousList.Add(thePreviousItem); 
} 
4 голосов
/ 29 марта 2012

Из документации:

Этот метод определяет равенство с помощью средства сравнения по умолчанию, как это определено реализацией объекта метода IEquatable (Of T) .Equals для T (тип значений).в списке).

Если вы не внедрили IEquatable<T>.Equals, он использует значение по умолчанию, равное ссылочному равенству.Кроме того, вы реализовали IEquatable<T>.Equals, но не сделали это должным образом.

Например, thepreviousitem id = 1 и name = test И если у меня есть другой объект с тем же идентификатором и тем же именем, он все равно будетдобавьте это ...

Вам нужно что-то вроде

class Foo : IEquatable<Foo> {
    public int Id { get; private set; }
    public string Name { get; private set; }
    public Foo(int id, string name) {
        this.Id = id;
        this.Name = name;
    }
    public bool Equals(Foo other) {
        return this.Id == other.Id && this.Name == other.Name;
    }
}

Наконец, если вы собираетесь многократно проверять наличие дубликатов, вам не следуетт List<T>.Вы должны использовать HashSet<T>.

2 голосов
/ 29 марта 2012

Из ваших комментариев к другим ответам звучит то, что вы не хотите переопределять Equals.

Вместо этого вы можете сделать это:

if (thePreviousList.Any(item => thePreviousItem.id == item.id && thePreviousItem.name == item.name))
{

}
else
{
    thePreviousList.Add(thePreviousItem);
}
1 голос
/ 29 марта 2012

Поскольку List<>.Contains проверяет ссылки , не проверяя свойства объектов в списке.

Чтобы это работало, вы должны переопределить Equals, а для лучшей практики переопределить GetHashCode. Правило должно состоять в том, что когда Equals возвращает true, должен быть возвращен тот же хеш-код.

Для вас должно быть что-то вроде следующего:

public override bool Equals(object obj)
{
   var i = obj as YourType;
   if(i == null) return false;

   return i.Id == this.Id && i.Name == this.Name;
}

public override int GetHashCode()
{
   return this.Id.GetHashCode() ^ this.Name.GetHashCode();
}
...