C#中ArrayList扩容后哈希码未变,为何内存地址看似相同?
ArrayList扩容后哈希码未变化的原因解析
你混淆了ArrayList实例的哈希码和它内部存储数组的哈希码。你调用的是a.GetHashCode(),得到的是ArrayList对象本身的哈希值,而非它内部用来存储元素的数组的哈希值。
ArrayList是一个包装类,它内部通过一个字段(比如_items)持有存储元素的数组。当容量占满扩容时,确实会创建新数组并复制旧元素,但ArrayList对象本身在堆上的内存地址并没有改变——你始终持有的是同一个ArrayList实例的引用,所以它的哈希码自然不会变化。
你可以通过反射获取内部数组的哈希码来验证这一点:
using System.Reflection; ArrayList a = new ArrayList(); a.Add(4); a.Add(4); a.Add(4); a.Add(4); // 获取内部_items数组的哈希码 FieldInfo field = typeof(ArrayList).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance); Array oldArray = (Array)field.GetValue(a); Console.WriteLine(oldArray.GetHashCode()); // 旧数组的哈希码 a.Add(5); Array newArray = (Array)field.GetValue(a); Console.WriteLine(newArray.GetHashCode()); // 新数组的哈希码,与旧数组不同
核心要点:
- ArrayList对象的引用未发生改变,因此它的哈希码保持不变
- 内部存储数组是ArrayList的一个成员字段,扩容时该字段指向新数组,但ArrayList实例本身的内存地址(及哈希码)不受影响
- 该现象和垃圾回收器(GC)无关,GC仅负责回收不再被引用的旧数组,不会修改现有ArrayList实例的内存位置
内容的提问来源于stack exchange,提问作者Mostafa Ahmed
相关产品推荐
相关产品推荐

