c# – 用于Annoymous类型的IEqualityComparer
首先我看到了
IEqualityComparer for anonymous type并且那里的答案没有回答我的问题,因为显而易见的原因是我需要IEqualityComparer而不是IComparer用于Linq的Distinct()方法.我也检查了其他答案,这些都没有解决方案……
问题 我有一些代码来操作和从DataTable中提取记录 var glext = m_dtGLExt.AsEnumerable(); var cflist = (from c in glext orderby c.Field<string>(m_strpcCCType),c.Field<string>(m_strpcCC),c.Field<string>(m_strpcCCDesc),c.Field<string>(m_strpcCostItem) select new { CCType = c.Field<string>(m_strpcCCType),CC = c.Field<string>(m_strpcCC),CCDesc = c.Field<string>(m_strpcCCDesc),CostItem = c.Field<string>(m_strpcCostItem) }).Distinct(); 但是我需要使用不同的方法来区分大小写.这里扔我的是使用匿名类型. 尝试解决方案1 如果我有SomeClass有明显的具体对象我可以做 public class SumObject { public string CCType { get; set; } public string CC { get; set; } public string CCDesc { get; set; } public string CostItem { get; set; } } 我显然可以做到这一点 List<SumObject> lso = new List<SumObject>() { new SumObject() { CCType = "1-OCC",CC = "300401",CCDesc = "Rooney",CostItem = "I477" },new SumObject() { CCType = "1-OCC",CCDesc = "Zidane",CostItem = "I677" },CCDesc = "Falcao",CostItem = "I470" },}; var e = lso.Distinct(new SumObjectComparer()); // Great :] 哪里 class SumObjectComparer : IEqualityComparer<SumObject> { public bool Equals(SumObject x,SumObject y) { if (Object.ReferenceEquals(x,y)) return true; if (Object.ReferenceEquals(x,null) || Object.ReferenceEquals(y,null)) return false; return x.CCType.CompareNoCase(y.CCType) == 0 && x.CC.CompareNoCase(y.CC) == 0 && x.CCDesc.CompareNoCase(y.CCDesc) == 0 && x.CostItem.CompareNoCase(y.CostItem) == 0; } public int GetHashCode(SumObject o) { if (Object.ReferenceEquals(o,null)) return 0; int hashCCType = String.IsNullOrEmpty(o.CCType) ? 0 : o.CCType.ToLower().GetHashCode(); int hashCC = String.IsNullOrEmpty(o.CC) ? 0 : o.CC.ToLower().GetHashCode(); int hashCCDesc = String.IsNullOrEmpty(o.CCDesc) ? 0 : o.CCDesc.ToLower().GetHashCode(); int hashCostItem = String.IsNullOrEmpty(o.CostItem) ? 0 : o.CostItem.ToLower().GetHashCode(); return hashCCType ^ hashCC ^ hashCCDesc ^ hashCostItem; } } 但是,在上面的Linq查询中使用匿名类型会让我失望. 尝试解决方案2 为了尝试另一个解决方案(因为我在其他地方有相同的问题),我生成了以下通用比较器类 public class GenericEqualityComparer<T> : IEqualityComparer<T> { Func<T,T,bool> compareFunction; Func<T,int> hashFunction; public GenericEqualityComparer(Func<T,bool> compareFunction,Func<T,int> hashFunction) { this.compareFunction = compareFunction; this.hashFunction = hashFunction; } public bool Equals(T x,T y) { return compareFunction(x,y); } public int GetHashCode(T obj) { return hashFunction(obj); } } 所以我可以尝试做 var comparer = new GenericEqualityComparer<dynamic>( (x,y) => { /* My equality stuff */ },o => { /* My hash stuff */ }); 但是这会将返回的值转换为IEnumerable< dynamic>这反过来影响我即将使用的cflist,因此在以下查询中,连接失败. var cf = (from o in cflist join od in glext on new { o.CCType,o.CC,o.CCDesc,o.CostItem } equals new { CCType = od.Field<string>(m_strpcCCType),CC = od.Field<string>(m_strpcCC),CCDesc = od.Field<string>(m_strpcCCDesc),CostItem = od.Field<string>(m_strpcCostItem) } into c select new { ... } 由于大量使用此代码,我不想进入IEnumerable< T> s进行丑陋的转换… 题 有没有办法可以为我的匿名类型创建IEquailityComparer? 谢谢你的时间. 解决方法
当然.您只需要使用类型推断.例如,你可以有类似的东西: public static class InferredEqualityComparer { public static IEqualityComparer<T> Create<T>( IEnumerable<T> example,bool> equalityCheck,int> hashCodeProvider) { return new EqualityComparerImpl<T>(equalityCheck,hashCodeProvider); } private sealed class EqualityComparerImpl<T> : IEqualityComparer<T> { // Implement in the obvious way,remembering the delegates and // calling them appropriately. } } 然后: var glext = m_dtGLExt.AsEnumerable(); var query = from c in glext orderby ... select new { ... }; var comparer = InferredEqualityComparer.Create(query,(x,y) => { ... },o => { ... } ); var distinct = query.Distinct(comparer); 基本上,该方法的第一个参数仅用于类型推断,因此编译器可以计算出用于lambda表达式参数的类型. 您可以通过创建匿名类型的示例来提前创建比较器: var sample = new[] { new { ... } }; var comparer = InferredExqualityComparer.Create(sample,...); var distinct = (... query here ... ).Distinct(comparer); 但是每当你改变查询时,你也必须改变样本. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 正则表达式 方括号表达式 区间表达式
- xml – NServiceBus端点是否可以使用不同的序列化程序处理和
- sqlite学习笔记8:C语言中使用sqlite之创建表
- 设计模式:反向控制和依赖注入(Inversion of control and De
- cllocationmanager – Swift中的CLLocation Manager获取用户
- oracle varchar 和 varchar2 的区别
- Oracle 解锁
- Git 的基本操作、开发流程、实用技巧总结(陈彦贝)
- XML的解析——读取节点的值和内容 (只有一级子节点)
- c – std :: unordered_map :: emplace问题与私有/删除的复