You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何修改数组元素后,List的Contains()仍判定该数组存在?

为什么List<int[]>和List调用Contains()的判定结果不同?

我编写了两段C#代码:第一段创建List<int[]>集合three_number_sums,将数组_3Ints_arr添加到集合后修改其元素值,使用Contains()判定时仍认为该数组存在;第二段创建List<string>集合words,将字符串word添加后重新赋值为新字符串,Contains()则判定新字符串不存在。想知道这两种情况判定结果不同的原因。

第一段代码(数组示例)

List<int[]> three_number_sums = new List<int[]>();

int[] _3Ints_arr = { 2, 6, 9 };

three_number_sums.Add(_3Ints_arr); // 将数组存入List,此时数组元素为2,6,9

_3Ints_arr[0] = 1;
_3Ints_arr[1] = 10;
_3Ints_arr[2] = 100;  // 数组元素变为1,10,100

if(!three_number_sums.Contains(_3Ints_arr))  // 判定结果为存在,不会执行Add
    three_number_sums.Add(_3Ints_arr);

第二段代码(字符串示例)

List<string> words = new List<string>();

string word = "apple";

words.Add(word);  // 将字符串存入List,此时内容为"apple"

word = "orange";  // 字符串变量指向新内容"orange"

if (!words.Contains(word))  // 判定结果为不存在,执行Add
   words.Add(word);

核心原因解析

List<T>.Contains() 默认使用EqualityComparer<T>.Default实现相等性判断,不同类型的比较逻辑本质差异导致了结果不同:

1. 数组(int[])的判定逻辑

数组是普通引用类型,默认的相等性比较是引用相等——即判断两个变量是否指向内存中的同一个对象实例:

  • 当你把_3Ints_arr添加到List时,List存储的是该数组对象的内存引用地址。
  • 修改数组元素的操作(如_3Ints_arr[0] = 1)只是改变了这个引用指向的数组对象内部的内容,引用本身没有发生变化(仍然指向同一块内存)。
  • 调用Contains(_3Ints_arr)时,List会遍历内部元素,对比每个元素的引用是否和传入的_3Ints_arr一致,结果自然是一致的,因此返回true,不会执行后续的Add操作。

2. 字符串(string)的判定逻辑

字符串是不可变的引用类型,它的特殊性导致了行为差异:

  • 初始时word = "apple",变量word指向内存中存储"apple"的字符串对象,添加到List后,List存储的是这个"apple"对象的引用。
  • 执行word = "orange"时,由于字符串不可变,不会修改原来的"apple"对象内容,而是在内存中创建一个全新的"orange"字符串对象,并让变量word指向这个新的内存地址。
  • 调用Contains(word)时,传入的是"orange"对象的引用,而List中只有"apple"对象的引用,两者指向不同的内存对象,因此返回false,执行后续的Add操作。

扩展:如何让数组的Contains比较元素内容?

如果需要让List<int[]>.Contains()比较数组的元素内容而非引用,可以自定义相等比较器:

public class ArrayEqualityComparer<T> : IEqualityComparer<T[]>
{
    public bool Equals(T[] x, T[] y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        if (x.Length != y.Length) return false;
        
        for (int i = 0; i < x.Length; i++)
        {
            if (!EqualityComparer<T>.Default.Equals(x[i], y[i]))
                return false;
        }
        return true;
    }

    public int GetHashCode(T[] obj)
    {
        if (obj == null) return 0;
        int hash = 17;
        foreach (var item in obj)
        {
            hash = hash * 31 + (item == null ? 0 : item.GetHashCode());
        }
        return hash;
    }
}

// 使用方式
if (!three_number_sums.Contains(_3Ints_arr, new ArrayEqualityComparer<int>()))
    three_number_sums.Add(_3Ints_arr);

内容的提问来源于stack exchange,提问作者der chuan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 19:30:50