C# List<T>.IndexOf()检索机制及自定义类匹配问题
解答结论
传入新创建的同字段值MyClass实例调用IndexOf时,不会返回列表中原有实例的索引,最终返回值为-1。
另外你贴的测试代码存在语法问题:IndexOf()需要传入要查找的对象作为参数,无参调用无法编译通过,正确写法是int index = my_list.IndexOf(mc);。
核心原因
- 你定义的
MyClass属于引用类型,在没有重写Equals()、GetHashCode()方法,也没有自定义相等比较器的前提下,List<T>.IndexOf()默认对引用类型做引用相等性判断:只有两个变量指向堆内存中同一个对象实例时,才会判定二者相等。 - 你在
SearchList方法中通过new创建的mc对象,和之前TestFunction里添加到列表的mc对象,虽然内部my_field字段值完全相同,但二者是内存中完全独立的两个实例,引用地址不一致,因此默认比较逻辑会判定二者不相等,自然找不到原有项的索引。
实现按字段值匹配查找的方法
如果需要让字段值相同的不同实例能被IndexOf正确识别,有两种常用方案:
重写类的相等判断逻辑
重写MyClass的Equals和GetHashCode方法,让相等判断从默认的引用比较改为值比较,示例代码如下:internal class MyClass { public MyClass() { } private string my_field; public string MyField { get { return my_field; } set { my_field = value; } } public override bool Equals(object obj) { if (obj is MyClass other) { return string.Equals(this.my_field, other.my_field); } return false; } public override int GetHashCode() { return my_field?.GetHashCode() ?? 0; } }重写完成后,只要两个实例的
my_field值一致,哪怕是独立创建的不同对象,IndexOf也能返回第一个匹配项的索引。不修改类定义,用查找方法传入匹配规则
如果不想改动MyClass本身的逻辑,可以直接调用FindIndex方法,手动传入字段匹配的委托,不需要依赖默认的相等判断:// 按MyField属性值查找第一个匹配项的索引 int index = my_list.FindIndex(item => item.MyField == "test1");
内容的提问来源于stack exchange,提问作者CodeJunkie
相关产品推荐
相关产品推荐

