Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List.Contains doesn't work properly

Tags:

c#

list

linq

I have a list which contains objects but these objests aren't unique in the list. I wrte this code to make unique them in another list:

 foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => !resultSet.Contains(categoryProductsResult)))
 {
    resultSet.Add(categoryProductsResult);
 }

But at the end resultSet is the same with categoryProductsResults.

categoryProductsResult's second row :

enter image description here

resultSet first row:

enter image description here

As you can see resultSet's first row and categoryProductsResult's second row is the same but it adds the second row to resultSet.

Do you have any suggestion?

like image 350
cagin Avatar asked Feb 22 '13 09:02

cagin


2 Answers

Contains uses the default comparer which is comparing references since your class does not override Equals and GetHashCode.

class CategoryProductsResult
{
    public string Name { get; set; }
    // ...

    public override bool  Equals(object obj)
    {
        if(obj == null)return false;
        CategoryProductsResult other = obj as CategoryProductsResult;
        if(other == null)return false;
        return other.Name == this.Name;
    }

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

Now you can simply use:

resultSet = categoryProductsResults.Distinct().ToList();
like image 103
Tim Schmelter Avatar answered Sep 22 '22 15:09

Tim Schmelter


List uses the comparer returned by EqualityComparer.Default and according to the documentation for that:

The Default property checks whether type T implements the System.IEquatable(Of T) interface and, if so, returns an EqualityComparer(Of T) that uses that implementation. Otherwise, it returns an EqualityComparer(Of T) that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

So you can either implement IEquatable on your custom class, or override the Equals (and GetHashCode) methods to do the comparison by the properties you require. Alternatively you could use linq:

bool contains = list.Any(i => i.Id == obj.Id);

like image 25
Rajesh Subramanian Avatar answered Sep 18 '22 15:09

Rajesh Subramanian