使用的IEqualityComparer&LT的; T>接口和EqualityComparer< T>在C#类接口、LT、IEqualityComparer、EqualityComp

2023-09-02 21:40:03 作者:爱意忽起忽落.

我编程使用这是一个循环链表文章,为帮助。

在一个函数,查找在该列表中的节点与给定值

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&LT; T&GT;比较器的对象,这是与属性 EqualityComparer&LT初始化;在构造函数中的一个.DEFAULT ; T&GT。能否请您解释我使用这些接口的(的IEqualityComparer&LT; T&GT; )的想法和类( EqualityComparer&LT; T&GT; )在这里?我读了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&LT;在T&GT; 是将处理相等比较为您收集的接口。您的收藏将equiality比较委派到该接口。你可能会问,为什么不只是调用等于的方法?

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?

由于可以有几种可能的比较。让我们举个简单的例子:在ABCABC平等吗?这取决于。 ABC.Equals(ABC)==假,但如果你想不区分大小写?

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&LT;在T&GT;

布尔等于(T X,T Y); :此方法不正是你想要它期望:它返回如果 X 应被视为等于。就像数学的平等,它必须是: 反思:等于(X,X)==真 对称的:等于(X,Y)==等于(Y,X) 传递的:如果等于(X,Y)及和放大器;等于(Y,Z)然后等于(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 GetHash $ C $ C(T obj)以; 这个可能是棘手得到的权利。对于每个 OBJ ,它应该返回一个散列code wilth以下属性: 在它应该永远不会改变 如果等于(X,Y)然后 GetHash code(X)== GetHash code(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

请注意,这并不意味着,如果 GetHash code(X)== GetHash code(Y)然后等于(X,Y)。两个对象可以有相同的哈希值code,但可以不相等(可以有最多 0xFFFFFFFF的可能哈希值codeS毕竟)。

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

集合经常使用hash code整理自己的物品。例如,的HashSet 就会知道,如果两个对象不具有相同的哈希code,它们不会是平等的,因此可以相应地安排其桶。哈希codeS只是一种优化。

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&LT; T&GT; .DEFAULT ?这是一个conventient快捷键为的IEqualityComparer&LT; T&GT; 将使用对象自身的等于 GetHash code 功能。这是一个很好的默认值,因为这是你想要做的大部分时间是什么:当字符串可以有多种天然的比较类型,这不是整数,比如案例

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&LT; T&GT; .DEFAULT 将处理几个特殊的情况:

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

如果 T是IEquatable&LT; T&GT; ,它将使用 IEquatable&LT; T&GT; 接口 如果 T可为空&LT; U&GT; U是IEquatable&LT; U&GT; 将处理情况妥善 在其将优化为一对夫妇的特殊情况:字节[] 和int-BASD 枚举 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.