如何覆盖 .NET 泛型 List<MyType>.Contains(MyTypeInstance) 方法?

8

是否有可能,如果可以的话,我该如何覆盖一个普通的List<T>Contains方法,其中T是我的自定义类型?


从你的问题中不太清楚你需要实现什么。你是a)需要标准的Contains方法来处理你的自定义类型,还是b)在调用Contains时执行一些特殊逻辑? - Peter Lillevold
彼得,我所拥有的List<T>基本上在运行时不是内存中的,它是松散/弱引用到一个OODBMS。如果我在List上执行本地的 .net .Contains,它会从oodbms后端检索整个列表并在本地进行评估。因此,我想用适当的(后端)查询语法覆盖它。 - Jörg Battermann
@Jörg - 那么考虑到这一点,覆盖Equals / GetHashCode如何解决您的问题(@Can的答案)? - Peter Lillevold
它没有过早地输出“已解决”... 我最终/基本上所做的是编写一个 List<MyType> 的扩展方法,其中内部使用 OODBMS 查询语法检查存在性。 - Jörg Battermann
oodbms是接口变化敏感的,当添加新的接口时需要迁移路径,但在这一点上我并不真正需要。不过,你的答案确实给了我一个方向上的小推动。谢谢! - Jörg Battermann
5个回答

7

List<T> 使用 EqualityComparer<T>.Default 进行比较;这首先检查您的对象是否实现了 IEquatable<T>;否则,它将使用 object.Equals

因此,最简单的方法是重写 Equals(始终更新 GetHashCode 以匹配 Equals 中的逻辑)。或者,使用 LINQ:

bool hasValue = list.Any(x => x.Foo == someValue);

@Marc Gravell:所以如果我想测试两个只包含属性和字段的自定义类的“相等性”,我需要在我的类中实现IEquatable吗?当我假设两个类仅因为字段包含相同值而被认为是“相等”时,我一定很累了。 :/ ……感谢您的提示 ;) - IAbstract
@Marc Gravell:从技术上讲,它们包含什么并不重要。重要的是我要“正确地”实现IEquatable<MyClass>并选择应该决定另一个MyClass是否相等的字段。 - IAbstract
@dboarman - 没错。关于你的第一个观点,如果我没记错,结构体确实会像那样表现,所以你并没有离谱太远。 - Marc Gravell

5
为了实现自己的Contains函数,你可以创建一个类来实现IList接口。这样你的类就像是一个IList。你可以在内部使用真正的List来执行标准的操作。
class MyTypeList : IList<MyType>
{
    private List<MyType> internalList = new ...;

    public bool Contains(MyType instance)
    {

    }

    ....
}

2

你需要在你的类(MyType)中重写EqualsGetHashCode方法。


1
根据您在覆盖中具体的需求,您可能会使用Linq表达式来实现:
list.Any(x => x.Name.Equals("asdas", .....)) // whatever comparison you need

然后,您可以将其包装在扩展方法中以提高方便性。


0
如果您实现了自定义类型的equals方法,List的contains函数将会起作用。

不,List<T> 永远不会使用 == 运算符;只会使用 Equals 方法。 - Marc Gravell
虽然我认为它不应该被踩,但 Equals 是 true,已经修复了 (+1)。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接