自定义IEqualityComparer的Equals和GetHashCode方法未被调用,求原因
自定义IEqualityComparer未被调用?问题出在LINQ的延迟执行上!
最近遇到一个坑:用自定义的IEqualityComparer<Dictionary<string, object>>去比较两个字典列表,结果Equals和GetHashCode里的断点根本没触发,折腾了半天终于找到原因,给你捋一捋:
先还原你的问题场景
你写了这样的自定义比较器:
public class TestEqualityComparer : IEqualityComparer<Dictionary<string, object>> { public bool Equals(Dictionary<string, object> a, Dictionary<string, object> b) { return true; // 断点打在这,完全没触发 } public int GetHashCode(Dictionary<string, object> obj) { return 0; // 这里也是,没动静 } }
然后用Except方法做比较:
var a = new List<Dictionary<string, object>>(); var b = new List<Dictionary<string, object>>(); a.Add(new Dictionary<string, object> { ["id"] = 1, ["msg"] = "aaaaa" }); a.Add(new Dictionary<string, object> { ["id"] = 2, ["msg"] = "bbbbb" }); a.Add(new Dictionary<string, object> { ["id"] = 3, ["msg"] = "ccccc" }); b.Add(new Dictionary<string, object> { ["id"] = 1, ["msg"] = "zzzzz" }); b.Add(new Dictionary<string, object> { ["id"] = 2, ["msg"] = "bbbbb" }); b.Add(new Dictionary<string, object> { ["id"] = 4, ["msg"] = "ddddd" }); var except = a.Except(b, new TestEqualityComparer());
运行后断点毫无反应,是不是很懵?
问题根源:LINQ的延迟执行特性
其实问题出在LINQ的延迟执行上!Except是一个延迟执行的LINQ操作符,它在你调用的时候并不会立刻去执行比较逻辑,只是返回了一个IEnumerable<T>类型的"查询计划"而已。只有当你真正去枚举这个结果的时候(比如把它转成列表、数组,或者遍历它),才会触发Equals和GetHashCode的调用。
怎么解决?触发枚举就行
你只需要在定义except之后,加一行触发枚举的代码,比如把结果转成列表:
var exceptResult = except.ToList(); // 这一行执行的时候,断点就会命中了!
或者直接遍历结果:
foreach (var dict in except) { // 哪怕这里啥都不做,只要遍历就会触发比较逻辑 }
小提醒
LINQ里像Except、Where、Select、OrderBy这类方法都是延迟执行的,目的是为了性能优化——避免提前做不必要的计算。以后再遇到自定义比较器、自定义委托没触发的情况,先想想是不是没触发枚举操作~
内容的提问来源于stack exchange,提问作者devunt
相关产品推荐
相关产品推荐

