【问题标题】:IEqualityComparer for anonymous type匿名类型的 IEqualityComparer
【发布时间】:2009-07-01 22:09:26
【问题描述】:

我有这个

 var n = ItemList.Select(s => new { s.Vchr, s.Id, s.Ctr, s.Vendor, s.Description, s.Invoice }).ToList();
 n.AddRange(OtherList.Select(s => new { s.Vchr, s.Id, s.Ctr, s.Vendor, s.Description, s.Invoice }).ToList(););

如果允许,我愿意这样做

n = n.Distinct((x, y) => x.Vchr == y.Vchr)).ToList();

我尝试使用通用 LambdaComparer,但由于我使用匿名类型,因此没有与之关联的类型。

“帮帮我欧比旺克诺比,你是我唯一的希望”

【问题讨论】:

标签: linq lambda anonymous-types iequalitycomparer


【解决方案1】:

诀窍是创建一个仅适用于推断类型的比较器。例如:

public class Comparer<T> : IComparer<T> {
  private Func<T,T,int> _func;
  public Comparer(Func<T,T,int> func) {
    _func = func;
  }
  public int Compare(T x,  T y ) {
    return _func(x,y);
  }
}

public static class Comparer {
  public static Comparer<T> Create<T>(Func<T,T,int> func){ 
    return new Comparer<T>(func);
  }
  public static Comparer<T> CreateComparerForElements<T>(this IEnumerable<T> enumerable, Func<T,T,int> func) {
    return new Comparer<T>(func);
  }
}

现在我可以执行以下操作... hacky 解决方案:

var comp = n.CreateComparerForElements((x, y) => x.Vchr == y.Vchr);

【讨论】:

  • 非常漂亮。我认为,为了编写干净的代码,我应该创建一个接口用作 IEqualityComparer. 中的 T
  • 我无法解决这个问题。见下文。
【解决方案2】:

大多数时候,当您比较(相等或排序)时,您感兴趣的是选择要比较的键,而不是相等或比较方法本身(这是 Python 列表排序 API 背后的理念)。

有一个示例键相等比较器here

【讨论】:

    【解决方案3】:

    我注意到 JaredPar 的回答并没有完全回答这个问题,因为诸如 Distinct 和 except 之类的设置方法需要 IEqualityComparer&lt;T&gt; 而不是 IComparer&lt;T&gt;。下面假设一个 IEquatable 会有一个合适的 GetHashCode,它肯定有一个合适的 Equals 方法。

    public class GeneralComparer<T, TEquatable> : IEqualityComparer<T>
    {
        private readonly Func<T, IEquatable<TEquatable>> equatableSelector;
    
        public GeneralComparer(Func<T, IEquatable<TEquatable>> equatableSelector)
        {
            this.equatableSelector = equatableSelector;
        }
    
        public bool Equals(T x, T y)
        {
            return equatableSelector.Invoke(x).Equals(equatableSelector.Invoke(y));
        }
    
        public int GetHashCode(T x)
        {
            return equatableSelector(x).GetHashCode();
        }
    }
    
    public static class GeneralComparer
    {
        public static GeneralComparer<T, TEquatable> Create<T, TEquatable>(Func<T, TEquatable> equatableSelector)
        {
            return new GeneralComparer<T, TEquatable>(equatableSelector);
        }
    }
    

    使用与 JaredPar 的答案相同的静态类技巧推断。

    更笼统地说,您可以提供两个Funcs:Func&lt;T, T, bool&gt; 用于检查相等性,Func&lt;T, T, int&gt; 用于选择哈希码。

    【讨论】:

    • 虽然 JaredPar 的回答是关于比较器的,但它给出了如何去做的想法。
    • 在这种情况下,很高兴展示它在Distinct()等方法中的使用方式
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2012-08-12
    • 1970-01-01
    相关资源
    最近更新 更多