Pass a lambda expression in place of IComparer or IEqualityComparer or any single-method interface?

后端 未结 8 1946
闹比i
闹比i 2020-12-08 08:57

I happened to have seen some code where this guy passed a lambda expression to a ArrayList.Sort(IComparer here) or a IEnumerable.SequenceEqual(IEnumerable list, IEqualityCom

8条回答
  •  春和景丽
    2020-12-08 09:43

    I was also googling the web for a solution, but i didn't found any satisfying one. So i've created a generic EqualityComparerFactory:

    using System;
    using System.Collections.Generic;
    
    /// 
    /// Utility class for creating  instances 
    /// from Lambda expressions.
    /// 
    public static class EqualityComparerFactory
    {
        /// Creates the specified .
        /// The type to compare.
        /// The get hash code delegate.
        /// The equals delegate.
        /// An instance of .
        public static IEqualityComparer Create(
            Func getHashCode,
            Func equals)
        {
            if (getHashCode == null)
            {
                throw new ArgumentNullException(nameof(getHashCode));
            }
    
            if (equals == null)
            {
                throw new ArgumentNullException(nameof(equals));
            }
    
            return new Comparer(getHashCode, equals);
        }
    
        private class Comparer : IEqualityComparer
        {
            private readonly Func _getHashCode;
            private readonly Func _equals;
    
            public Comparer(Func getHashCode, Func equals)
            {
                _getHashCode = getHashCode;
                _equals = equals;
            }
    
            public bool Equals(T x, T y) => _equals(x, y);
    
            public int GetHashCode(T obj) => _getHashCode(obj);
        }
    }
    

    The idea is, that the CreateComparer method takes two arguments: a delegate to GetHashCode(T) and a delegate to Equals(T,T)

    Example:

    class Person
    {
        public int Id { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var list1 = new List(new[]{
                new Person { Id = 1, FirstName = "Walter", LastName = "White" },
                new Person { Id = 2, FirstName = "Jesse", LastName = "Pinkman" },
                new Person { Id = 3, FirstName = "Skyler", LastName = "White" },
                new Person { Id = 4, FirstName = "Hank", LastName = "Schrader" },
            });
    
            var list2 = new List(new[]{
                new Person { Id = 1, FirstName = "Walter", LastName = "White" },
                new Person { Id = 4, FirstName = "Hank", LastName = "Schrader" },
            });
    
    
            // We're comparing based on the Id property
            var comparer = EqualityComparerFactory.Create(
                a => a.Id.GetHashCode(),
                (a, b) => a.Id==b.Id);
            var intersection = list1.Intersect(list2, comparer).ToList();
        }
    }
    

提交回复
热议问题