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; } }
If there can be multiple then use Where. var comparer = new ObjComparer(); var item = total_objs. FirstOrDefault(f => comparer. Equals(f, obj1));
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.
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.
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.
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.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With