如何使用自定义IEqualityComparer <t>参数进行内联工作

时间:2018-10-30 13:35:07

标签: linq function lambda parameters distinct

我需要多次调用来自不同IEnumerables的linq区别。 这些差异通常需要我仅在软件中使用一次的条件。 我发现创建用于通过代码库实现IEqualityComparer的类以执行区别的约束确实令人烦恼,因此我想弥补创建空白类的空白,该类允许指向作为区别的参数传递的lambda表达式。 / p>

为了传递自定义IEqualityComparer参数,我开发了以下类:

public class InlineComparer<T>
{
    private class LambdaBasedComparer : IEqualityComparer<T>
    {
        public LambdaBasedComparer(Func<T, int> getHashCode)
        {
            fGetHashCode = getHashCode;
        }

        public bool Equals(T x, T y)
        {
            return x?.GetHashCode() == y?.GetHashCode();
        }

        private Func<T, int> fGetHashCode { get; set; }

        public int GetHashCode(T obj)
        {
            return fGetHashCode(obj);
        }
    }


    public static IEqualityComparer<T> GetComparer(Func<T, int> getHashCode)
    {
        return new LambdaBasedComparer(getHashCode);
    }
}

您如何看待?希望对您有所帮助!

当然,此帮助程序的完整实现将此类使用到类似于“ IEnumerable.Distinct(Func getHashCode)”的扩展方法中,但是我想强调一下使用lambda传递独特代码的可能性。

1 个答案:

答案 0 :(得分:0)

如果相等对象为GetHashCode()返回相同的值,则它们将声明两个对象相等。当然,在定义自己的平等比较器时,您可以随意定义平等的概念,只要平等是自反的,对称的和可传递的(x == x;如果x == y,则y == x ;如果x == y和y == x,则x == z)。

您的平等比较器符合这些规则,因此您可以使用它。

但是!它将是一个有用的比较器吗?

您要使用特殊的相等比较器代替默认的相等比较器,因为您需要对两个对象的(非)相等性进行特殊定义。

通常,在设计过程中,应首先定义对象的相等性。如果这样做了,并且想使用LambdaBasedComparer,则必须创建一个哈希函数,该哈希函数将为不同的对象返回不同的值。

通常,哈希函数有一个要求:两个相等的对象应返回相同的哈希值。不需要两个不同的对象。

只有Int32.MaxValue的Hash值不同,因此,如果您设计的类具有大于此值的可能的不相等实例,则不能使用比较器。一个简单的例子:尝试创建一个使用普通等式的LambdaBasedComparer<long>

但是,即使您的类只能创建一半的Int32.MaxValue实例,也很难创建合适的哈希函数来为不同的对象生成唯一的哈希值。

最后,如果使用等式来比较派生类,则等式不会非常直观。考虑Person类和派生类Employee和Customer。

IEqualityComparer<Person> personComparer = new LambdBasedComparer<Person>(...);

Person p = new Person(...);
Person e = new Employee(...);
Person c = new Customer(...);

现在我可以说,某个不是雇员的人可以等于您的一名雇员。但是您会说员工将等于客户吗?

总结:您认为比较器有一个简单的解决方案,但是很难为您的相等性定义创建合适的哈希函数,并且测试该哈希函数可能会更加困难