2012-10-16 28 views
2

我写了下面的代码来实现在可能的最基本的方式Linq.Distinct(IEqualityComparer)显着,但是simpleCollection回报2项,而是如果1实施中的LINQ C#

奇怪的是,我已经注意到,在Equals断点永远不会命中。

难道这与我执行GetHashCode()有关吗?

public class testobjx 
    { 
     public int i { get; set; } 
    } 

    public class mytest 
    { 
     public Main() 
     { 
      var simpleCollection = new[] { new testobjx() { i = 1 }, new testobjx() { i = 1 } }.Distinct(new DistinctCodeType()); 
      var itemCount = simpleCollection.Count();//this should return 1 not 2. 
     } 
    } 

    public class DistinctCodeType : IEqualityComparer<testobjx> 
    { 
     public bool Equals(testobjx x, testobjx y) 
     { 
      return x.i == y.i; 
     } 

     public int GetHashCode(testobjx obj) 
     { 
      return obj.GetHashCode(); 
     } 
    } 
+0

如果x,y或obj为空,该怎么办? – n8wrl

+0

如果GetHashCode的结果不匹配,则甚至不检查Equals。处理你的GetHashCode实现。 –

+1

供参考:http://msmvps.com/blogs/jon_skeet/archive/2010/12/30/reimplementing-linq-to-objects-part-14-distinct.aspx –

回答

5

尝试:

public int GetHashCode(testobjx obj) 
{ 
    if (obj == null) return 0; 
    return obj.i.GetHashCode(); 
} 
+1

如果不是只包含一个整数“i”的类,它包含10个独立的整数或任何其他数量的复杂属性,那么该怎么办? – maxp

+0

@maxp,看看这个答案http://stackoverflow.com/a/263416/1009661。像ReSharper这样的VS插件也能够生成一些通用接口和方法的实现,包括GetHashCode。 – 2kay

1

的GetHashCode对于对象的默认实现是基于对象的实例,使具有相同值testobjx的两个实例有不同的散列码。你需要修改你的GetHashCode方法来询问对象的属性。如果对象具有多个属性,则需要确定哪些对象唯一标识对象并从中组合一个散列码。

+0

GetHashCode的默认实现不能唯一标识一个对象。它不能。它有40亿个可能的价值,并且最可靠的是有超过40亿个可能的对象。但即便如此,在开始接近40亿之前,您将开始获得[哈希码相互冲突](http://blogs.msdn.com/b/ericlippert/archive/2010/03/22/socks-birthdays-and -hash-collisions.aspx)。小心使用GetHashCode关联唯一性。这不是它的意图。它有助于平衡散列表。它缩小了事情的范围。但是一个合理的实现永远不会保证唯一性。 –