2015-12-15 108 views
1

我試圖比較Definition類型的兩個哈希集作爲EqualityComparer<T>.Default.Equals(value, oldValue)Definition定義如下檢查對象的HashSet是否相等

public class Definition 
{ 
    public string Variable { get; set; } 
    public HashSet<Location> LocationList { get; set; } 

    public override bool Equals(object obj) 
    { 
     Definition other = obj as Definition; 
     return other.Variable.Equals(this.Variable) && other.LocationList!= null &&this.LocationList != null 
      && other.LocationList.Count == this.LocationList.Count 
      && other.LocationList == this.LocationList; 
    } 

    public override int GetHashCode() 
    { 
     return this.Variable.GetHashCode()^this.LocationList.Count.GetHashCode();//^this.LocationList.GetHashCode(); 
    } 
} 

public class Location 
{ 
    public int Line { get; set; } 
    public int Column { get; set; } 
    public int Position { get; set; } 
    public string CodeTab { get; set; } 
    public Location(int line, int col, int pos, string tab) 
    { 
     Line = line; 
     Column = col; 
     Position = pos; 
     CodeTab = tab; 
    } 
    public override bool Equals(object obj) 
    { 
     Location other = obj as Location; 
     return this.CodeTab == other.CodeTab 
      && this.Position == other.Position 
      && this.Column == other.Column 
      && this.Line == other.Line; 
    } 
    public override int GetHashCode() 
    { 
     return this.CodeTab.GetHashCode()^this.Position.GetHashCode() 
      ^this.Column.GetHashCode()^this.Line.GetHashCode(); 
    } 
} 

不知何故對於類似的一組,其結果是,儘管保持相同的所有信息返回false。唯一的區別是某些元素的位置互換,但我知道HashSet在比較時不會保留或檢查順序。任何人都可以告訴我這裏出了什麼問題嗎?

PS:我試着取消註釋this.LocationList.GetHashCode()也沒有工作。

+0

這是一個'HashSet的'不是'HashSet的'但你的狀態,你想比較_「定義的兩個哈希集」_。所以你的問題要麼是錯誤的,要麼是你的代碼做了一些不同的事情。 –

+0

'value'和'oldValue'是'Definition'類型。 – Sreeja

回答

0

您需要創建對於集的比較器:

var setComparer = HashSet<Location>.CreateSetComparer(); 
return other.Variable.Equals(this.Variable) && setComparer.Equals(this.LocationList, other.LocationList); 
1

EqualityComparer<T>.Default將尋找實施IEquatable<T>的對象。否則,它將推遲到ObjectEqualityComparer,它只是檢查引用相等。這就是爲什麼你比較引用時看到錯誤的原因。

你實際上想要做的是明確實施IEquatable<Location>。注意你應該讓你的屬性不可變這正常工作:

public class Location : IEquatable<Location> 
{  
    public Location(int line, int col, int pos, string tab) 
    { 
     Line = line; 
     Column = col; 
     Position = pos; 
     CodeTab = tab; 
    } 

    public int Line { get; private set; } 
    public int Column { get; private set; } 
    public int Position { get; private set; } 
    public string CodeTab { get; private set; } 

    public bool Equals(Location other) 
    { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return string.Equals(CodeTab, other.CodeTab) && Column == other.Column && Line == other.Line && Position == other.Position; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     if (obj.GetType() != this.GetType()) return false; 
     return Equals((Location) obj); 
    } 

    public static bool operator ==(Location left, Location right) 
    { 
     return Equals(left, right); 
    } 

    public static bool operator !=(Location left, Location right) 
    { 
     return !Equals(left, right); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      var hashCode = (CodeTab != null ? CodeTab.GetHashCode() : 0); 
      hashCode = (hashCode*397)^Column; 
      hashCode = (hashCode*397)^Line; 
      hashCode = (hashCode*397)^Position; 
      return hashCode; 
     } 
    } 
} 

現在,如果你看一下由Default創建的類型EqualityComparer,你會看到GenericEqualityComparer<Location>

Console.WriteLine(EqualityComparer<Location>.Default.GetType())