2009-07-01 102 views
29

我有这个的IEqualityComparer匿名类型

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但因为即时通讯使用匿名类型的尝试没有类型与之相关联。

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

+3

伟大的问题,我只是在寻找同样的事情。令人难以置信的是它不在标准库中。 – orip 2009-08-06 14:57:21

+0

它可以帮助[包裹在IEqualityComparer中的委托](http://stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer) – marbel82 2016-10-07 15:10:58

回答

16

关键是要建立一个比较器,仅适用于推断类型。例如:

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

现在,我可以做以下...哈克解决方案:

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

非常漂亮。虽然我认为,为了编写干净的代码,我应该创建一个接口,以在IEqualityComparer中使用T作为参数。 – kjgilla 2009-07-02 02:32:07

3

很多时候你比较(相等或排序)你有兴趣选择键时来比较,而不是相等或比较方法本身(这是Python列表排序API背后的想法)。

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

0

我注意到JaredPar的回答并不完全回答这个问题,因为像Distinct和Except这样的设置方法不需要IEqualityComparer<T>而不是IComparer<T>。以下假设一个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的答案中使用了与静态类别技巧相同的推理。

为了更一般,您可以提供两个Func s:一个Func<T, T, bool>来检查相等性,并且Func<T, T, int>选择一个哈希码。