簡體   English   中英

Distinct 不適用於 IEquatable<t></t>

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM