Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the IEqualityComparer

I have some bells in my database with the same number. I want to get all of them without duplication. I created a compare class to do this work, but the execution of the function causes a big delay from the function without distinct, from 0.6 sec to 3.2 sec!

Am I doing it right or do I have to use another method?

reg.AddRange(     (from a in this.dataContext.reglements      join b in this.dataContext.Clients on a.Id_client equals b.Id      where a.date_v <= datefin && a.date_v >= datedeb      where a.Id_client == b.Id      orderby a.date_v descending       select new Class_reglement      {          nom  = b.Nom,          code = b.code,          Numf = a.Numf,      })     .AsEnumerable()     .Distinct(new Compare())     .ToList());  class Compare : IEqualityComparer<Class_reglement> {     public bool Equals(Class_reglement x, Class_reglement y)     {         if (x.Numf == y.Numf)         {             return true;         }         else { return false; }     }     public int GetHashCode(Class_reglement codeh)     {         return 0;     } } 
like image 569
Akrem Avatar asked Jul 14 '11 14:07

Akrem


People also ask

How to use IEqualityComparer in LinQ?

If there can be multiple then use Where. var comparer = new ObjComparer(); var item = total_objs. FirstOrDefault(f => comparer. Equals(f, obj1));

What is IEqualityComparer?

IEqualityComparer is a very important interface for comparer tasks in the LinQ world. The next extended methods have an overload with this parameter type: Contains, Distinct, Except, Intersect, GrouBy, GroupJoin, Join, SecuenceEqual, ToDictionary, ToLookUp and Union.

What collection would use an IEqualityComparer T to enforce uniqueness?

The Distinct extension method returns a new collection of unique elements from the given collection. The Distinct extension method doesn't compare values of complex type objects. You need to implement IEqualityComparer<T> interface in order to compare the values of complex types.

How do you override equals method in C#?

Because Complex is a value type, it cannot be derived from. Therefore, the override to Equals(Object) method need not call GetType to determine the precise run-time type of each object, but can instead use the is operator in C# or the TypeOf operator in Visual Basic to check the type of the obj parameter.


2 Answers

Your GetHashCode implementation always returns the same value. Distinct relies on a good hash function to work efficiently because it internally builds a hash table.

When implementing interfaces of classes it is important to read the documentation, to know which contract you’re supposed to implement.1

In your code, the solution is to forward GetHashCode to Class_reglement.Numf.GetHashCode and implement it appropriately there.

Apart from that, your Equals method is full of unnecessary code. It could be rewritten as follows (same semantics, ¼ of the code, more readable):

public bool Equals(Class_reglement x, Class_reglement y) {     return x.Numf == y.Numf; } 

Lastly, the ToList call is unnecessary and time-consuming: AddRange accepts any IEnumerable so conversion to a List isn’t required. AsEnumerable is also redundant here since processing the result in AddRange will cause this anyway.


1 Writing code without knowing what it actually does is called cargo cult programming. It’s a surprisingly widespread practice. It fundamentally doesn’t work.

like image 53
Konrad Rudolph Avatar answered Sep 18 '22 13:09

Konrad Rudolph


Try This code:

public class GenericCompare<T> : IEqualityComparer<T> where T : class {     private Func<T, object> _expr { get; set; }     public GenericCompare(Func<T, object> expr)     {         this._expr = expr;     }     public bool Equals(T x, T y)     {         var first = _expr.Invoke(x);         var sec = _expr.Invoke(y);         if (first != null && first.Equals(sec))             return true;         else             return false;     }     public int GetHashCode(T obj)     {         return obj.GetHashCode();     } } 

Example of its use would be

collection = collection     .Except(ExistedDataEles, new GenericCompare<DataEle>(x=>x.Id))     .ToList();  
like image 21
suneelsarraf Avatar answered Sep 18 '22 13:09

suneelsarraf