如何使用IEqualityComparer
我的数据库中有一些相同的号码。 我想让所有这些都不重复。 然后我创build一个比较类来完成这个工作,但是函数的执行会使得函数有一个很大的延迟,从0.6秒到3.2秒没有区别!
我是对的还是要用另一种方法?
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; } }
难怪,考虑到你的GetHashCode
实现始终返回相同的值。 Distinct
依靠一个好的哈希函数来有效地工作。
在实现类的接口时, 你需要先阅读他们的文档 ,否则你不知道你应该实现哪个合约。 1
在你的代码中,解决scheme是将GetHashCode
转发到Class_reglement.Numf.GetHashCode
并在那里适当地实现。
除此之外,您的Equals
方法充满了不必要的代码。 它可以被重写如下(相同的语义,¼的代码,更可读):
public bool Equals(Class_reglement x, Class_reglement y) { return x.Numf == y.Numf; }
此外, ToList
调用是不必要的和耗时的: AddRange
接受任何IEnumerable
因此不需要转换为List
。 AsEnumerable
在这里也是多余的,因为在AddRange
处理结果将导致这个问题。
1实现代码而不知道它实际上做了什么就被称为货物崇拜编程 。 这是一个非常普遍的做法。 它从根本上不起作用。
试试这个代码:
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(); } }
它的使用的例子是
collection = collection .Except(ExistedDataEles, new GenericCompare<DataEle>(x=>x.Id)) .ToList();
包含你的比较类(或者更确切地说是你需要使用的AsEnumerable
调用来实现它)意味着sorting逻辑从基于数据库服务器转到数据库客户端(你的应用程序)。 这意味着您的客户端现在需要检索并处理大量的logging,这些logging总是会效率低下,从而在数据库上执行适当的索引的查找。
您应该尝试开发一个满足您的要求的where子句,请参阅使用带有LINQ to Entities Except子句的IEqualityComparer以获取更多详细信息。
只需执行GetHashCode
和NULL
validation的代码:
public class Class_reglementComparer : IEqualityComparer<Class_reglement> { public bool Equals(Class_reglement x, Class_reglement y) { if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; return x.Numf == y.Numf; } public int GetHashCode(Class_reglement product) { //Check whether the object is null if (Object.ReferenceEquals(product, null)) return 0; //Get hash code for the Numf field if it is not null. int hashNumf = product.hashNumf == null ? 0 : product.hashNumf.GetHashCode(); return hashNumf; } }
例子: Class_reglement由Numf区分的列表
List<Class_reglement> items = items.Distinct(new Class_reglementComparer());