使用 IEqualityComparer<T>接口和 EqualityComparer<T>C#中的类 [英] Using of IEqualityComparer<T> interface and EqualityComparer<T> class in C#

查看:13
本文介绍了使用 IEqualityComparer<T>接口和 EqualityComparer<T>C#中的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用这篇文章编写一个循环链表 作为帮助.

I am programming a circular linked list using this article as help.

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

In a function that searches in this list for a node with a given value

    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;comparer 对象,它在构造函数之一中使用属性 EqualityComparer.Default 进行初始化.你能解释一下使用这些接口 (IEqualityComparer) 和类 (EqualityComparer) 的想法吗?我读过MSDN,但我不明白它们的工作原理和使用原理.

an author uses an IEqualityComparer<T> comparer object, which is initialized with a property EqualityComparer<T>.Default in one of constructors. Can you please explain me an idea of using of these interface (IEqualityComparer<T>) and class (EqualityComparer<T>) here? I had read MSDN, but I didn't understand the principles of working and using of them.

推荐答案

IEqualityComparer 是一个接口,它将处理您的集合的相等比较.您的集合会将等价性比较委托给此接口.你可能会问,为什么不直接调用 Equals 方法呢?

IEqualityComparer<in T> is an interface that will handle equality comparisons for your collection. Your collection will delegate equiality comparisons to this interface. You may ask, why don't just call the Equals method?

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

Because there can be several kinds of possible comparisons. Let's take an easy example: are "Abc" and "ABC" equal? It depends. "Abc".Equals("ABC") == false but what if you want case insensitivity?

这就是为什么你的集合应该委托相等比较到不同的类.通过组合类,您将遵守单一职责原则:您的集合知道如何存储项目,而相等比较器知道它们是否相等.

This is why your collection should delegate the equality comparisons to a different class. By composing classes, you'll respect the single responsibility principle: Your collection knows how to store the items, and the equality comparer knows if they're equal.

集合示例:

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 类.

Here you have two completely different set semantics using the same HashSet class.

现在,IEqualityComparer 中有什么?

  • bool Equals(T x, T y);:这个方法的作用正如你所期望的:它返回 true if x 应该被认为等于 y.就像数学上的等式一样,它必须:
    • 自反:Equals(x, x) == true
    • 对称:Equals(x, y) == Equals(y, x)
    • 传递:if Equals(x, y) &&Equals(y, z) 然后 Equals(x, z)
    • bool Equals(T x, T y);: This method does just what you'd expect it to: it returns true if x should be considered equal to y. Just like the mathematical equality, it must be:
      • reflexive: Equals(x, x) == true
      • symmetric: Equals(x, y) == Equals(y, x)
      • transitive: if Equals(x, y) && Equals(y, z) then Equals(x, z)
      • int GetHashCode(T obj); 这个可能更难做对.对于每个 obj,它应该返回一个具有以下属性的哈希码:
        • 它永远不应该改变
        • if Equals(x, y) then GetHashCode(x) == GetHashCode(y)
        • 应该尽可能少地发生冲突
        • int GetHashCode(T obj); this one may be trickier to get right. For each obj, it should return a hash code wilth the following properties:
          • it should never change
          • if Equals(x, y) then GetHashCode(x) == GetHashCode(y)
          • there should be as few collisions as possible

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

          Note that this does not imply that if GetHashCode(x) == GetHashCode(y) then Equals(x, y). Two objects can have the same hash code but be inequal (there can be at most 0xFFFFFFFF possible hash codes after all).

          集合经常使用哈希码来组织它们的项目.例如,HashSet 会知道如果两个对象没有相同的哈希码,它们就不会相等,因此可以相应地组织它的桶.哈希码只是一种优化.

          Collections often use the hash code to organize their items. For example, the HashSet will know that if two objects don't have the same hash code, they won't be equal and thus can organize its buckets accordingly. Hash codes are just an optimization.

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

          Now, what's EqualityComparer<T>.Default? It's a conventient shortcut for an IEqualityComparer<T> that will use an object's own Equals and GetHashCode functions. This is a good default value as this is what you want to do most of the time: while strings can have multiple natural comparison types, this is not the case for integers for instance.

          EqualityComparer.Default 将处理一些特殊情况:

          EqualityComparer<T>.Default will handle a couple special cases:

          • 如果T是IEquatable,它将使用IEquatable接口
          • 如果 T 为 Nullable 并且 U 为 IEquatable 它将正确处理这种情况
          • 它将针对几个特殊情况进行优化:byte[] 和 int-basd Enum.
          • if T is IEquatable<T>, it will use the IEquatable<T> interface
          • if T is Nullable<U> and U is IEquatable<U> it will handle the case properly
          • it will optimize for a couple special cases: byte[] and int-basd Enum.

          这篇关于使用 IEqualityComparer&lt;T&gt;接口和 EqualityComparer&lt;T&gt;C#中的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆