shole
shole

Reputation: 4094

LINQ Distinct() not work even implemented Equals() & GetHashCode()

I have done some research before asking this simple question, but still cannot make it work...

Below is my object class and my LINQ query

  public class ItemGridViewModel: IEqualityComparer<ItemGridViewModel>
  {
        public ItemGridViewModel() { }

        public int ItemID { get; set; }
        public string Code { get; set; }
        public string Description { get; set; }
        public decimal Qty { get; set; }

        public bool Equals(ItemGridViewModel x, ItemGridViewModel y) 
        {
             return x.ItemID == y.ItemID; 
        }
        public int GetHashCode(ItemGridViewModel obj) { return obj.ItemID; }
  }

 

var query = (from ccp in CostCenterParaQuery
     where ccp.CostCentreID != null && costCenterList2.Contains(ccp.CostCentreID.Value)
     select ccp into g
     from s in StoreRoomQuery
     where s.CostCentreCode == g.CostCentreCode
     select s into g2
     from b in BinItemStatQuery
     where b.Qty > 0 && b.IsFrozen == "N" && b.StoreroomID == g2.StoreroomID
     select b into g3
     from i in ItemsQuery
     where ((i.ItemID == g3.ItemID) && 
         (whereClause.Code == null || i.ItemCode == whereClause.Code) &&   
         (whereClause.Description == null || i.Description == whereClause.Description))
     select new ItemGridViewModel()
     {
         Qty = g3.Qty,
         Code = i.ItemCode,
         Description = i.Description,
         ItemID = i.ItemID
     }).Distinct();

But the result set obviously duplicate several ItemGridViewModel with same ItemID...

What is the possibly reasons & how can I solve it?

Upvotes: 2

Views: 1273

Answers (2)

Justin Niessner
Justin Niessner

Reputation: 245429

You've implemented the wrong interface in your ItemGridViewModel. Based on the usage, I think you wanted IEquatable<T>.

IEqualityComparer<T> is used to build a separate object who's responsibility is solely to compare objects of type T:

public class ItemGridViewModel
{
    // Your implementation
}

public class ItemGridViewModelEqualityComparer : IEqualityComparer<ItemGridViewModel> 
{
    public bool Equals(ItemGridViewModel a, ItemGridViewModel b)
    {
        return a.ItemID == b.ItemID;
    }

    public int GetHashCode(ItemGridViewModel o)
    {
        return o.ItemID.GetHashCode();
    }
}

And then your call to distinct would be:

// rest of query
select new ItemGridViewModel()
{
    // assignment
}).Distinct(new ItemGridViewModelEqualityComparer());

Upvotes: 7

Kirill Polishchuk
Kirill Polishchuk

Reputation: 56172

Implement IEquatable<T> interface.

public class ItemGridViewModel: IEquatable<ItemGridViewModel>
{
    ...
}

Upvotes: 1

Related Questions