使用 IEqualityComparer<T>接口和 EqualityComparer<T>C#中的类 [英] Using of IEqualityComparer<T> interface and EqualityComparer<T> class in 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
对象,它在构造函数之一中使用属性 EqualityComparer
进行初始化.你能解释一下使用这些接口 (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
ifx
应该被认为等于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 returnstrue
ifx
should be considered equal toy
. 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)
thenEquals(x, z)
int GetHashCode(T obj);
这个可能更难做对.对于每个obj
,它应该返回一个具有以下属性的哈希码:- 它永远不应该改变
- if
Equals(x, y)
thenGetHashCode(x) == GetHashCode(y)
- 应该尽可能少地发生冲突
int GetHashCode(T obj);
this one may be trickier to get right. For eachobj
, it should return a hash code wilth the following properties:- it should never change
- if
Equals(x, y)
thenGetHashCode(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)
thenEquals(x, y)
. Two objects can have the same hash code but be inequal (there can be at most0xFFFFFFFF
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
的一种方便快捷方式,它将使用对象自己的Equals
和GetHashCode
函数.这是一个很好的默认值,因为这是您大部分时间想要做的:虽然字符串可以有多种自然比较类型,但例如整数就不是这种情况.Now, what's
EqualityComparer<T>.Default
? It's a conventient shortcut for anIEqualityComparer<T>
that will use an object's ownEquals
andGetHashCode
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-basdEnum
.
- if
T is IEquatable<T>
, it will use theIEquatable<T>
interface - if
T is Nullable<U>
andU is IEquatable<U>
it will handle the case properly - it will optimize for a couple special cases:
byte[]
and int-basdEnum
.
这篇关于使用 IEqualityComparer<T>接口和 EqualityComparer<T>C#中的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- reflexive:
- 自反: