2015-12-15 112 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())