C# 为什么不';t列表<;T>;。GetHashCode和ObservableCollection<;T>;。GetHashCode评估他们的项目?

C# 为什么不';t列表<;T>;。GetHashCode和ObservableCollection<;T>;。GetHashCode评估他们的项目?,c#,hashcode,C#,Hashcode,我认为奇怪的是,这些集合的GetHashCode函数没有将它们的hashcode基于列表中的项目 我需要这项工作,以提供脏检查(您有未保存的数据)。 我已经编写了一个覆盖GetHashCode方法的包装类,但我发现这不是默认实现,这很奇怪 我想这是一个性能优化 class Program { static void Main(string[] args) { var x = new ObservableCollection<test>();

我认为奇怪的是,这些集合的GetHashCode函数没有将它们的hashcode基于列表中的项目

我需要这项工作,以提供脏检查(您有未保存的数据)。 我已经编写了一个覆盖GetHashCode方法的包装类,但我发现这不是默认实现,这很奇怪

我想这是一个性能优化

class Program
{
    static void Main(string[] args)
    {
        var x = new ObservableCollection<test>();
        int hash = x.GetHashCode();
        x.Add(new test("name"));
        int hash2 = x.GetHashCode();

        var z = new List<test>();
        int hash3 = z.GetHashCode();
        z.Add(new test("tets"));
        int hash4 = z.GetHashCode();

        var my = new CustomObservableCollection<test>();
        int hash5 = my.GetHashCode();
        var test = new test("name");
        my.Add(test);
        int hash6 = my.GetHashCode();
        test.Name = "name2";
        int hash7 = my.GetHashCode();
    }
}

public class test
{
    public test(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is test)
        {
            var o = (test) obj;
            return o.Name == this.Name;
        }
        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}

public class CustomObservableCollection<T> : ObservableCollection<T>
{
    public override int GetHashCode()
    {
        int collectionHash = base.GetHashCode();

        foreach (var item in Items)
        {
            var itemHash = item.GetHashCode();
            if (int.MaxValue - itemHash > collectionHash)
            {
                collectionHash = collectionHash * -1;
            }
            collectionHash += itemHash;
        }
        return collectionHash;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var x=新的ObservableCollection();
int hash=x.GetHashCode();
x、 添加(新测试(“名称”);
int hash2=x.GetHashCode();
var z=新列表();
int hash3=z.GetHashCode();
z、 增加(新试验(“tets”);
int hash4=z.GetHashCode();
var my=新的CustomObservableCollection();
int hash5=my.GetHashCode();
var测试=新测试(“名称”);
添加(测试);
int hash6=my.GetHashCode();
test.Name=“name2”;
int hash7=my.GetHashCode();
}
}
公开课考试
{
公共测试(字符串名称)
{
名称=名称;
}
公共字符串名称{get;set;}
公共覆盖布尔等于(对象对象对象)
{
如果(obj是测试)
{
var o=(测试)obj;
返回o.Name==this.Name;
}
返回基数等于(obj);
}
公共覆盖int GetHashCode()
{
返回Name.GetHashCode();
}
}
公共类CustomObservableCollection:ObservableCollection
{
公共覆盖int GetHashCode()
{
int collectionHash=base.GetHashCode();
foreach(项目中的var项目)
{
var itemHash=item.GetHashCode();
if(int.MaxValue-itemHash>collectionHash)
{
collectionHash=collectionHash*-1;
}
collectionHash+=itemHash;
}
返回集合哈希;
}
}

GetHashCode的关键是以轻量级的方式反映
Equals()
逻辑


List.Equals()
继承
Object.Equals()
,而
Object.Equals()
通过引用比较相等,这样列表就不基于它的项,而是列表本身
GetHashCode
的关键是以轻量级的方式反映
Equals()
逻辑


List.Equals()
继承
Object.Equals()
,和
Object.Equals()
通过引用比较相等性,因此列表不基于其项目,而是列表本身列表的Equals/GetHashCode检查引用相等性,而不是内容相等性。这背后的原因是,列表既是可变的对象,也是按引用(而不是结构)的对象。因此,每次更改内容时,哈希代码都会更改


哈希代码的常见用例是哈希表(例如
Dictionary
或HashSet),当第一次将哈希插入表中时,哈希表根据哈希对其项进行排序。如果表中已存在的对象的哈希值发生更改,则可能无法再找到该对象,从而导致行为不稳定。

列表的Equals/GetHashCode检查引用相等,而不是内容相等。这背后的原因是,列表既是可变的对象,也是按引用(而不是结构)的对象。因此,每次更改内容时,哈希代码都会更改


哈希代码的常见用例是哈希表(例如
Dictionary
或HashSet),当第一次将哈希插入表中时,哈希表根据哈希对其项进行排序。如果表中已存在的对象的哈希值发生更改,则可能无法再找到该对象,从而导致行为不稳定。

如果更改了,则会破坏一些属性。即:

GetHashCode返回的整数永远不会更改

由于列表的内容可以更改,因此其哈希代码也可以更改

GetHashCode的实现必须非常快

根据列表的大小,可能会降低其哈希代码的计算速度


另外,我认为您不应该使用对象的哈希代码来检查数据是否脏

如果它这样做了,它会打破一些规则。即:

GetHashCode返回的整数永远不会更改

由于列表的内容可以更改,因此其哈希代码也可以更改

GetHashCode的实现必须非常快

根据列表的大小,可能会降低其哈希代码的计算速度


另外,我认为您不应该使用对象的哈希代码来检查数据是否脏

如果有两种类型,它们的行为类似于
List
,通常可以与之互换使用,但是可以与
GetHashCode
Equals
方法一起使用,这些方法可以根据身份序列定义等价性,或者
等于
GetHashCode
中封装的项目的行为。然而,要使这些方法高效运行,需要类包含缓存其哈希值的代码,但在修改集合时使缓存的哈希值无效或更新(在列表作为字典键存储时修改列表是不合法的,但删除、修改并重新添加列表应该是合法的,并且非常希望避免这种修改需要重新散列列表的全部内容)。不值得让普通列表通过努力来支持这种行为,而代价是降低对从不散列的列表的操作速度;也不值得根据它们应该在me中寻找的等效类型来定义多种类型的列表、多种类型的字典等mber或应暴露于