c# – 用于Annoymous类型的IEqualityComparer

c# – 用于Annoymous类型的IEqualityComparer,第1张

概述首先我看到了 IEqualityComparer for anonymous type并且那里的答案没有回答我的问题,因为显而易见的原因是我需要IEqualityComparer而不是IComparer用于Linq的Distinct()方法.我也检查了其他答案,这些都没有解决方案…… 问题 我有一些代码来 *** 作和从DataTable中提取记录 var glext = m_dtGLExt.AsEnum 首先我看到了 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?

谢谢你的时间.

解决方法

Is there a way I can create my an IEquailityComparer for my anonymous types?

当然.您只需要使用类型推断.例如,你可以有类似的东西:

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);

但是每当你改变查询时,你也必须改变样本.

总结

以上是内存溢出为你收集整理的c# – 用于Annoymous类型的IEqualityComparer全部内容,希望文章能够帮你解决c# – 用于Annoymous类型的IEqualityComparer所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1239399.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存