其他分享
首页 > 其他分享> > 通用List.Contains()中的值与引用相等

通用List.Contains()中的值与引用相等

作者:互联网

尝试#3简化此问题:

通用列表< T>可以包含任何类型-值或引用.当检查列表是否包含对象时,.Contains()使用默认的EqualityComparer< T>. T类型,并调用.Equals()(据我理解).如果未定义EqualityComparer,则默认比较器将调用.Equals().默认情况下,.Equals()调用.ReferenceEquals(),因此.Contains()仅在列表包含完全相同的对象时才返回true.

在需要重写.Equals()来实现值相等之前,默认情况下,默认比较器会说两个对象具有相同的值,则它们是相同的.我想不出哪一种情况对于引用类型来说是理想的.

我从@Enigmativity那里听到的是,实现IEqualityComparer< StagingDataRow>将为我键入的DataRow提供一个默认的相等比较器,而不是Object的默认比较器-允许我在StagingDataRow.Equals()中实现值相等逻辑.

问题:

>我理解正确吗?
>我是否保证.NET框架中的所有内容都将调用EqualityComparer< StagingDataRow> .Equals()而不是StagingDataRow.Equals()?
> IEqualityComparer< StagingDataRow> .GetHashCode(StagingDataRow obj)应该针对什么进行哈希处理,并且它应该返回与StagingDataRow.GetHashCode()相同的值?
>什么传递给IEqualityComparer< StagingDataRow> .GetHashCode(StagingDataRow obj)?我要查找的对象还是列表中的对象?都?有一个实例方法接受自己作为参数会很奇怪.

通常,重写.Equals()时,如何将值相等与引用相等分开?

原始代码行引发了这个问题:

//  For each ID, a collection of matching rows
Dictionary<string, List<StagingDataRow>> stagingTableDictionary;


StagingTableMatches.AddRange(stagingTableDictionary[perNr].Where(row => !StagingTableMatches.Contains(row)));

.

解决方法:

好的,让我们先处理一些误解:

By default, .Equals() calls .ReferenceEquals(), so .Contains() will only return true if the list contains the exact same object.

这是正确的,但仅适用于引用类型.值类型默认情况下将实现very slow reflection-based Equals函数,因此,您最好将其覆盖.

I can’t think of a single case where that would be desirable for a reference type.

哦,我敢肯定你可以…字符串是实例的引用类型:)

What I’m hearing from @Enigmativity is that implementing IEqualityComparer<StagingDataRow> will give my typed DataRow a default equality comparer that will be used instead of the default comparer for Object – allowing me to implement value equality logic in StagingDataRow.Equals().

嗯…不

IEqualityComaprer< T>是一个接口,可让您将相等性比较委派给其他对象.如果您希望类使用其他默认行为,则可以实现IEquatable< T>并委托对象.实际上,覆盖object.Equals和object.GetHashCode足以更改默认的相等比较行为,而且还可以实现IEquatable< T>.还有其他好处:

>显然,您的类型具有自定义的相等比较逻辑-考虑自记录代码.
>它提高了值类型的性能,因为它避免了不必要的装箱(这在object.Equals中发生)

因此,对于您的实际问题:

Am I understanding that correctly?

您似乎对此仍然有些困惑,但是请放心:)

谜题实际上建议您创建实现IEqualityComparer< T>的其他类型.好像您误解了那部分.

Am I guaranteed that everything in the .NET framework will call EqualityComparer<StagingDataRow>.Equals() instead of StagingDataRow.Equals()

默认情况下,(正确编写的)框架数据结构将把相等性比较委托给EqualityComparer< StagingDataRow> .Default,它将依次委托给StagingDataRow.Equals.

What should IEqualityComparer<StagingDataRow>.GetHashCode(StagingDataRow obj) hash against, and should it return the same value as StagingDataRow.GetHashCode()

不必要.它应该是自洽的:如果myEqualitycomaprer.Equals(a,b),则必须确保myEqualitycomaprer.GetHashCode(a)== myEqualitycomaprer.GetHashCode(b).

它可以是与StagingDataRow.GetHashCode相同的实现,但不是必须的.

What is passed to IEqualityComparer<StagingDataRow>.GetHashCode(StagingDataRow obj)? The object I’m looking for or the object in the list? Both? It would be strange to have an instance method accept itself as a parameter…

好吧,到目前为止,我希望您已经了解实现IEqualityComparer< T>的对象.是一个不同的对象,所以这应该是有道理的.

请阅读我对Using of IEqualityComparer interface and EqualityComparer class in C#的回答,以获取更深入的信息.

标签:gethashcode,iequatable,iequalitycomparer,linq,c
来源: https://codeday.me/bug/20191118/2029807.html