首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >IEqualityComparer<T>接口和EqualityComparer<T>类在C#中的应用

IEqualityComparer<T>接口和EqualityComparer<T>类在C#中的应用
EN

Stack Overflow用户
提问于 2014-10-05 13:19:31
回答 1查看 1.6K关注 0票数 1

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

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

代码语言:javascript
运行
复制
    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,但我不了解它们的工作和使用原则。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-05 13:25:15

IEqualityComparer<in T>是一个接口,它将处理集合的相等比较。您的集合将委托与此接口进行等量比较。您可能会问,为什么不直接调用Equals方法呢?

因为有几种可能的比较。让我们举一个简单的例子:"Abc""ABC"相等吗?那得看情况。"Abc".Equals("ABC") == false,但是如果你希望大小写不敏感呢?

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

一个集合的例子:

代码语言:javascript
运行
复制
var caseSensitive = new HashSet<string>(StringComparer.Ordinal) // The default anyway
{
    "Abc", "ABC"
};

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

其结果将是:

代码语言:javascript
运行
复制
caseSensitive.Count == 2
caseInsensitive.Count == 1

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

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

现在,IEqualityComparer<in T>中有什么

  • bool Equals(T x, T y);:这个方法做了您期望的事情:如果x应该被认为等于y,它会返回y。就像数学等式一样,它必须是 be:
    • 自反:Equals(x, x) == true
    • 对称:Equals(x, y) == Equals(y, x)
    • 传递性:如果Equals(x, y) && Equals(y, z)那么Equals(x, z)

  • int GetHashCode(T obj);这个可能是更棘手的正确。对于每个obj,它应该返回一个哈希代码,并使用以下属性:
    • 它永远不应该改变
    • 如果Equals(x, y)那么GetHashCode(x) == GetHashCode(y)
    • 应该尽量少碰撞。

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

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

现在,EqualityComparer<T>.Default是什么?它是IEqualityComparer<T>使用对象自己的EqualsGetHashCode函数的常规快捷方式。这是一个很好的默认值,因为这是大多数时候您想要做的:虽然字符串可以有多个自然比较类型,但是对于整数来说并非如此。

EqualityComparer<T>.Default将处理几个特例:

  • 如果是T is IEquatable<T>,它将使用IEquatable<T>接口
  • 如果T is Nullable<U>U is IEquatable<U>能正确处理这个案件
  • 它将对一些特殊情况进行优化:byte[]和int Enum
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26202921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档