繁体   English   中英

使用IEqualityComparer <T> 接口和EqualityComparer <T> C#中的类

[英]Using of IEqualityComparer<T> interface and EqualityComparer<T> class in C#

我正在编写循环链表,使用本文作为帮助。

在一个函数中,在此列表中搜索具有给定值的节点

    public Node<T> Find(T item)
    {
        Node<T> node = FindNode(head, item);
        return node;
    }

    Node<T> FindNode(Node<T> node, T valueToCompare)
    {
        Node<T> result = null;
        if (comparer.Equals(node.Value, valueToCompare))
            result = node;
        else if (result == null && node.Next != head)
            result = FindNode(node.Next, valueToCompare);
        return result;
    }

作者使用IEqualityComparer<T> comparer对象,该对象在其中一个构造函数中使用属性EqualityComparer<T>.Default进行初始化。 你能解释一下在这里使用这些接口( IEqualityComparer<T> )和类( EqualityComparer<T> )的想法吗? 我读过MSDN,但我不理解工作和使用它们的原理。

IEqualityComparer<in T>是一个接口,用于处理集合的相等比较。 您的收藏会将等同性比较委托给此界面。 您可能会问,为什么不直接调用Equals方法?

因为可以有几种可能的比较。 让我们举一个简单的例子: "Abc""ABC"相等? 这取决于。 "Abc".Equals("ABC") == false但是如果你想要不区分大小写怎么办?

这就是为什么您的集合应该相等比较委托给不同的类。 通过编写类,您将尊重单一责任原则:您的集合知道如何存储项目,并且相等比较器知道它们是否相等。

集合的示例:

var caseSensitive = new HashSet<string>(StringComparer.Ordinal) // The default anyway
{
    "Abc", "ABC"
};

var caseInsensitive = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
    "Abc", "ABC"
};

结果将是:

caseSensitive.Count == 2
caseInsensitive.Count == 1

caseSensitive.Contains("aBc") == false
caseInsensitive.Contains("aBc") == true

在这里,您使用相同的HashSet类有两个完全不同的set语义。

现在, IEqualityComparer<in T>什么?

  • bool Equals(T x, T y); :此方法正如您所期望的那样:如果x应该被视为等于y则返回true 就像数学上的平等一样,它必须是:
    • 反身: Equals(x, x) == true
    • 对称: Equals(x, y) == Equals(y, x)
    • 传递:如果Equals(x, y) && Equals(y, z)Equals(x, z)
  • int GetHashCode(T obj); 这个可能更难以正确。 对于每个obj ,它应返回具有以下属性的哈希码:
    • 它永远不应该改变
    • if Equals(x, y)GetHashCode(x) == GetHashCode(y)
    • 应该尽可能少的碰撞

注意,这并不意味着如果GetHashCode(x) == GetHashCode(y)Equals(x, y) 两个对象可以具有相同的哈希码但是不相等(毕竟最多可以有0xFFFFFFFF哈希码)。

集合通常使用哈希代码来组织其项目。 例如, HashSet将知道如果两个对象不具有相同的哈希码,则它们将不相等,因此可以相应地组织其桶。 哈希码只是一种优化。

现在,什么是EqualityComparer<T>.Default 它是IEqualityComparer<T>一个IEqualityComparer<T>快捷方式,它将使用对象自己的EqualsGetHashCode函数。 这是一个很好的默认值,因为这是你想要在大多数时间做的事情:虽然字符串可以有多个自然比较类型,但例如整数不是这种情况。

EqualityComparer<T>.Default将处理几个特殊情况:

  • 如果T is IEquatable<T> ,它将使用IEquatable<T>接口
  • 如果T is Nullable<U>U is IEquatable<U>则它将正确处理该情况
  • 它将针对一些特殊情况进行优化: byte[]和int-basd Enum

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM