[英]Distinct is not working with IEquatable<T>
I have a class Bar that looks like this:我有一个 class Bar,看起来像这样:
public class Bar : IEquatable<Bar>
{
public string Stringbar1{ get; set; }
public string Stringbar2{ get; set; }
public string Stringbar3{ get; set; }
public string Stringbar4{ get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public EnumFoo1 Enumfoo1{ get; set; }
public bool IsBar{ get; set; }
public List<string> StringBars{ get; set; }
[BsonSerializer(SerializerType = typeof(NullableDateTimeOffsetToUtcSerializer))]
public DateTimeOffset? FooDate{ get; set; }
public string Stringbar5{ get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public EnumFoo2 EnumFoo2 { get; set; }
public string StringBar6{ get; set; }
public int Foo{ get; set; }
public Bar()
{
EnumFoo1= EnumFoo1.Unknown;
EnumFoo2= EnumFoo2.Other;
StringBars= new List<string>();
}
public bool Equals(Bar other)
{
if (other == null)
{
return false;
}
return Stringbar1 == other.Stringbar1&& Stringbar2== other.Stringbar2 && Stringbar3== other.Stringbar3 && Stringbar4== other.Stringbar4 && EnumFoo1== other.EnumFoo1 && IsBar== other.IsBar&& BothNullOrEquals(StringBars,other.StringBars) && StringBar5==other.StringBar5&& FooDate== other.FooDate && ContractType == other.ContractType && LotNumber == other.LotNumber && Rank == other.Rank;
}
public override int GetHashCode()
{
var stringbar1Hashcode = Stringbar1== null ? 0 : Stringbar1.GetHashCode();
var stringbar2HashCode = Stringbar2== null ? 0 : Stringbar2.GetHashCode();
var stringbar3CodeHashCode = Stringbar3== null ? 0 : Stringbar3.GetHashCode();
var EnumFoo1HashCode = EnumFoo1.GetHashCode();
var Stringbar4HashCode = Stringbar4== null ? 0 : Stringbar4.GetHashCode();
var isBarHashCode = IsBar.GetHashCode();
var strtingBarsHashCode = StringBars== null ? 0 : StringBars.GetHashCode();
var stringbar5HashCode = Stringbar5== null ? 0 : Stringbar5.GetHashCode();
var fooDateHashCode = FooDate== null ? 0 : FooDate.GetHashCode();
var enumFoo2HashCode= EnumFoo2.GetHashCode();
var stringBar6HasCode = StringBar6== null ? 0 : StringBar6.GetHashCode();
var fooHashCode= Foo.GetHashCode();
return stringbar1Hashcode ^ stringbar2HashCode ^ stringbar3CodeHashCode ^ EnumFoo1HashCode ^ Stringbar4HashCode ^ isBarHashCode ^ strtingBarsHashCode ^ stringbar5HashCode ^ fooDateHashCode ^ enumFoo2HashCode ^ stringBar6HasCode ^ fooHashCode ;
}
public static bool BothNullOrEquals<T>(IEnumerable<T> left, IEnumerable<T> right)
{
if (left == null && right == null)
{
return true;
}
if (left != null && right != null)
{
return left.SequenceEqual(right);
}
return false;
}
}
Equals is working as expected but it seems that I am missing something when it comes to GetHashCode cause extension methods like LINQ Distinct are not working as expected. Equals 按预期工作,但在 GetHashCode 方面我似乎遗漏了一些东西,因为 LINQ Distinct 等扩展方法未按预期工作。 and I know that Distinct uses the GetHashCode method to compare references so any idea what am I doing wrong?
而且我知道 Distinct 使用 GetHashCode 方法来比较引用所以知道我做错了什么吗?
The problem I can see is in the我能看到的问题是
var strtingBarsHashCode = StringBars== null ? 0 : StringBars.GetHashCode();
Please, note that for List<string> StringBars
HashCode is reference based : hash codes are guaranteed to be equal if StringBars
share the same reference only.请注意,对于
List<string> StringBars
HashCode 是基于引用的:如果StringBars
仅共享相同的引用,则 hash 代码保证相等。 However, you compare these collections by more relaxing scheme:但是,您可以通过更轻松的方案来比较这些 collections:
BothNullOrEquals(StringBars, other.StringBars)
So, StringBars
doesn't have to share the same reference to be equal, they should have equal items only .因此,
StringBars
不必共享相同的引用才能相等,它们应该只有相等的项。 Note that GetHashCode
must not return different codes for equal instances.请注意,
GetHashCode
不得为相同的实例返回不同的代码。
Don't make GetHashCode
that elaborated;不要制作详细说明的
GetHashCode
; please, note, that GetHashCode
should be a fast estimation of Equals
;请注意,
GetHashCode
应该是对Equals
的快速估计; to be so 2.. 3
selective properties are enough:如此
2.. 3
选择性属性就足够了:
public override int GetHashCode() {
// Let .Net check for null and combine hash codes for you
return HashCode.Combine(Stringbar1, Stringbar2, Stringbar3);
}
Edit: If you can't use HashCode.Combine
, well let it be ^
, but, please, don't put many fields and properties into GetHashCode
just a few the most selective ones:编辑:如果您不能使用
HashCode.Combine
,那么就让它成为^
,但是,请不要将许多字段和属性放入GetHashCode
中,只是一些最有选择性的:
public override int GetHashCode() {
// Let .Net check for null and combine hash codes for you
return (Stringbar1?.GetHashCode() ?? 0) ^
(Stringbar2?.GetHashCode() ?? 0) ^
(Stringbar3?.GetHashCode() ?? 0);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.