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

使用ObjectList.Contains(foo)时对象列表无法正确比较的技术问题

解决C# List.Contains()无法正确判断对象存在的问题

我来帮你搞定这个问题!你遇到的核心原因是:默认情况下,List<T>.Contains()使用的是引用相等性判断——它只会检查两个对象是不是内存中的同一个实例,而不会去比较对象的内容。你的Book类没有重写Equals()和GetHashCode()方法,所以哪怕两本书的ISBN、标题完全一致,只要是不同的实例,Contains()就会返回false。

下面给你两种常用的解决方案,你可以根据场景选择:

方案一:重写Book类的Equals()和GetHashCode()方法

如果Book类是你自己维护的,优先用这个方法——这样所有涉及对象相等性的操作(比如Contains、IndexOf、Distinct等)都会自动按内容判断,一劳永逸。

因为ISBN是书籍的唯一标识,我们可以基于它来实现相等性逻辑:

public class Book {
    public string Title;
    public string Author;
    public string ISBN;

    public Book(string title, string author, string iSBN) {
        Title = title;
        Author = author;
        ISBN = iSBN;
    }

    // 重写Equals方法,基于ISBN判断对象内容是否相等
    public override bool Equals(object obj) {
        // 如果是同一个实例,直接返回true
        if (ReferenceEquals(this, obj)) return true;
        // 检查obj是否是Book类型
        if (obj is not Book otherBook) return false;
        // 忽略大小写比较ISBN(可根据业务需求调整为严格区分)
        return string.Equals(ISBN, otherBook.ISBN, StringComparison.OrdinalIgnoreCase);
    }

    // 必须同时重写GetHashCode,和Equals的逻辑保持一致(.NET的约定)
    public override int GetHashCode() {
        // 用ISBN的哈希值,确保Equals为true的对象哈希值相同
        return ISBN?.ToLowerInvariant().GetHashCode() ?? 0;
    }
}

关键说明:

  • 为什么要同时重写GetHashCode()?因为.NET的规则是:如果两个对象通过Equals()返回true,它们的GetHashCode()必须返回相同的值,否则会导致哈希集合(比如HashSet<T>)出现异常行为,虽然List<T>.Contains()不依赖哈希,但遵循约定是良好的编程习惯。
  • 你可以根据业务需求调整相等性逻辑:比如如果需要同时比较Title和Author,只需要在Equals()里添加对应的判断即可,但ISBN通常足够作为唯一标识。

方案二:使用自定义IEqualityComparer(无需修改Book类)

如果你无法修改Book类(比如它是第三方库中的类),可以用这个方法——通过传入自定义的相等性比较器,让Contains()按你的规则判断。

首先定义一个比较器类:

public class BookEqualityComparer : IEqualityComparer<Book> {
    public bool Equals(Book x, Book y) {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        // 同样基于ISBN判断,逻辑和方案一一致
        return string.Equals(x.ISBN, y.ISBN, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(Book obj) {
        return obj?.ISBN?.ToLowerInvariant().GetHashCode() ?? 0;
    }
}

然后在调用Contains()时传入这个比较器:

// 假设你要检查的目标书籍对象是targetBook
Book targetBook = ...;
// 使用自定义比较器判断是否存在
bool exists = NewUsersBooks.Contains(targetBook, new BookEqualityComparer());

额外注意事项

  • 字符串比较规则:示例中用了StringComparison.OrdinalIgnoreCase忽略大小写,如果你的业务场景中ISBN是严格区分大小写的,改成StringComparison.Ordinal即可。
  • null值处理:两个方案都考虑了null的情况,避免出现空引用异常。

内容的提问来源于stack exchange,提问作者Melvin Langvik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:53:53