![](/img/trans.png)
[英]LINQ Distinct with EqualityComparer<T>.Default: IEquatable<T> implementation ignored?
[英]Distinct is not working with IEquatable<T>
我有一個 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 按預期工作,但在 GetHashCode 方面我似乎遺漏了一些東西,因為 LINQ Distinct 等擴展方法未按預期工作。 而且我知道 Distinct 使用 GetHashCode 方法來比較引用所以知道我做錯了什么嗎?
我能看到的問題是
var strtingBarsHashCode = StringBars== null ? 0 : StringBars.GetHashCode();
請注意,對於List<string> StringBars
HashCode 是基於引用的:如果StringBars
僅共享相同的引用,則 hash 代碼保證相等。 但是,您可以通過更輕松的方案來比較這些 collections:
BothNullOrEquals(StringBars, other.StringBars)
因此, StringBars
不必共享相同的引用才能相等,它們應該只有相等的項。 請注意, GetHashCode
不得為相同的實例返回不同的代碼。
不要制作詳細說明的GetHashCode
; 請注意, GetHashCode
應該是對Equals
的快速估計; 如此2.. 3
選擇性屬性就足夠了:
public override int GetHashCode() {
// Let .Net check for null and combine hash codes for you
return HashCode.Combine(Stringbar1, Stringbar2, Stringbar3);
}
編輯:如果您不能使用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.