C# 需要一些关于HashSet工作原理的解释吗

C# 需要一些关于HashSet工作原理的解释吗,c#,collections,C#,Collections,这就是我所拥有的: class A { // The uniqueness of instance must be detected by this property public string Key { get; set; } // There are other properties } var set = HashSet<A>() A类 { //此属性必须检测实例的唯一性 公共字符串密钥{get;set;} //还有其他属性 } var set=HashSe

这就是我所拥有的:

class A
{
  // The uniqueness of instance must be detected by this property
  public string Key { get; set; }

  // There are other properties
}

var set = HashSet<A>()
A类
{
//此属性必须检测实例的唯一性
公共字符串密钥{get;set;}
//还有其他属性
}
var set=HashSet()
我的一般目的是:

  • 通过
    属性值提供
    集合
    中实例的标识

  • 使此集合尽可能快地用于包含操作

回答以下问题可能有助于我达到这一目的:

  • 运行像
    Contains
    Add
    这样必须确定实例唯一性的方法时使用的是什么:GetHashCode()或IEquatable?最有可能是GetHashCode(),因为HashSet声明搜索速度非常快
  • 默认
    String.GetHashCode()
    实现不能保证两个不同字符串的哈希值的唯一性,所以如何在考虑性能的情况下提供唯一性
  • HashSet是否使用了IEquatable

  • 注意:他的集合仅在运行时创建和销毁,不保存到数据库中

    集合通常使用
    Object.GetHashCode()
    Object.Equals()
    获取哈希代码并检查是否相等。无法使
    对象。GetHashCode()
    为除最简单的对象外的所有对象返回唯一的哈希代码-哈希代码只有32位宽,并且每个内部状态超过32位的对象都无法映射到唯一的哈希代码。因此,
    Object.Equals()
    用于检查哈希代码冲突时的精确相等性

    因此,您必须使用合适的实现覆盖上述两种方法

    public override Int32 GetHashCode()
    {
        // If this.Key may be null you have to handle this case.
        return this.Key.HashCode();
    }
    
    public override Boolean Equals(Object obj)
    {
        var other = obj as A;
    
        return (other != null) && (this.Key == other.Key);
    }
    

    或者,您可以使用
    HashSet
    构造函数接受
    IEqualityComparer
    并将这两种方法外部化,例如,如果您无法控制要添加到集合中的类型的源代码。只需使用合适的方法创建一个实现接口的类,并将该类的一个实例传递给
    HashSet
    构造函数。

    更重要的问题是,当一条记录位于集合中时,
    键的值能否更改?很抱歉,丢失了它:不,它不能谢谢!只需要一些小的澄清:1)为什么相等(objectobj),但不相等?我肯定装箱/拆箱的速度相当慢。2) 我是否正确地理解了for
    Contains
    call HashSet首先运行
    GetHashCode
    ,然后检查现有的哈希代码,如果找到这样的哈希,它将运行
    Equals
    ,以便识别实例是相同的还是新的,对吗?@YMC哈希集可以被认为是列表数组。首先,它使用来自
    GetHashCode
    的结果查找要搜索的列表,然后使用
    Equals
    查找列表中是否存在元素。这就是为什么如果使用默认实现(不向构造函数传递
    IEqualityComarer
    )如果两个对象相等,但它们返回不同的哈希代码,则哈希集可能表示该项存在于哈希集中,也可能不表示该项存在于哈希集中。理论上,哈希集实现可以使用
    IEquatable
    ,但
    HashSet
    的文档没有说明它是这样做的。这在文档中可能没有遗漏,因为您可以通过将
    EqualityComparer.Default
    传递给
    HashSet
    的构造函数来间接使用
    IEquatable
    ,如果类型实现了它,则默认比较器将使用
    IEquatable
    。有关
    EqualityComparer.Default
    如何工作的更多详细信息,请参见MSDN。Scott,因此,如果我将自己的
    EqualityComparer
    传递到构造函数中而不进行装箱/拆箱,它的工作速度会更快,对吗?在这种情况下,我不需要实现
    Equals(objectobj)
    ,对吗?您有一个类,因此不需要装箱,只需对
    Object
    back进行强制转换,开销最小。如上所述,您可以使用
    EqualityComparer.Default
    间接使用
    IEquatable
    的实现。很难说什么会更快,因为差异(可能)非常小。除非你真的遇到性能问题,否则不要在意。然后实施和配置所有选项,并选择最快或最好的选项。在优化代码时,猜测是不够的。