IEqualityComparer for anonymous type

后端 未结 3 1500
梦谈多话
梦谈多话 2020-12-05 04:55

I have this

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


        
相关标签:
3条回答
  • 2020-12-05 05:06

    Most of the time when you compare (for equality or sorting) you're interested in choosing the keys to compare by, not the equality or comparison method itself (this is the idea behind Python's list sort API).

    There's an example key equality comparer here.

    0 讨论(0)
  • 2020-12-05 05:21

    I note that JaredPar's answer does not quite answer the question since the set methods like Distinct and Except require an IEqualityComparer<T> not an IComparer<T>. The following assumes that an IEquatable will have a suitable GetHashCode, and it certainly has a suitable Equals method.

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

    Where the same inference from a static class trick is used as in JaredPar's answer.

    To be more general you could provide two Funcs: a Func<T, T, bool> to check equality and Func<T, T, int> to select a hash code.

    0 讨论(0)
  • 2020-12-05 05:27

    The trick is to create a comparer that only works on inferred types. For instance:

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

    Now I can do the following ... hacky solution:

    var comp = n.CreateComparerForElements((x, y) => x.Vchr == y.Vchr);
    
    0 讨论(0)
提交回复
热议问题