2010-02-17 55 views
11

组我有这个类如何通过自定义类型使用LINQ

public class Item 
{ 
     public Coordinate coordinate { get; set; } 
     ... 
     ... 
} 

有了坐标,其定义是这样的:

public class Coordinate 
{ 
     public Coordinate(float latitude, float longitude) 
     { 
      Latitude = latitude; 
      Longitude = longitude; 
     } 

     public float Latitude { get; private set; } 
     public float Longitude { get; private set; } 
} 

而且我希望有一个LINQ查询这样的:

var grouped = from it in items 
       group it by it.Coordinate into grp 
       select grp; 

As mentioned here by MSDN我认为这是可能的,如果我将覆盖坐标类上的等于:

如果您必须将 查询变量传递给其他方法,请使用指定类型。 使用 键为 自动实现的属性创建一个特殊类,然后重写等于 和GetHashCode方法。您也可以使用 结构,在这种情况下,您不必 严格地覆盖那些 方法。欲了解更多信息,请参阅如何 :实现一个不可变类 具有自动实现的属性

的Equals实现为协调类:

public override bool Equals(object obj) 
{ 
     var coord = obj as Coordinate; 
     if(coord == null) return false; 
     return (Latitude == coord.Latitude && Longitude == coord.Longitude); 
} 

我仍然不能得到通过类似的坐标我的LINQ查询到组作为我失败试验表明:

[TestMethod] 
public void GroupBy_3ItemsWith2DifferentCoordinates_Returns2Groups() 
{ 
    var items = new List<Item> 
     { 
      new Item {Coordinate = new Coordinate(10, 10)}, 
      new Item {Coordinate = new Coordinate(10, 10)}, 
      new Item {Coordinate = new Coordinate(12, 10)}, 
     }; 
    var grouped = from it in items 
        group it by it.Coordinate into g 
        select g; 
    Assert.AreEqual(2, grouped.Count()); 
} 

有一个过载将IEqualityComparer作为参数的GrouBy方法,但是使用group子句的等价方法是否存在? 我做错了什么?有什么想法吗?

回答

22

您已经显示了Equals实现,但没有显示GetHashCode。您需要覆盖这两个(并以一致的方式)以使分组工作。

样品的GetHashCode实现:

public override int GetHashCode() 
{ 
    int hash = 23; 
    hash = hash * 31 + Latitude.GetHashCode(); 
    hash = hash * 31 + Longitude.GetHashCode(); 
    return hash; 
} 

注意,对于准确平等比较float值始终是很危险的 - 但我至少希望你的单元测试通过,因为他们没有进行任何的计算。

+0

刚刚试了一下,这就是我失踪。非常感谢你:) public override int GetHashCode() return {((int)Latitude * 100)^((int)Longitude * 100); } – 2010-02-17 11:39:35

+0

如果这就是你的哈希代码正在做的事情,你应该确保你的相等代码匹配它 - 它们应该是彼此一致的。 – 2010-02-17 11:43:06

+0

Latitude.GetHashCode()^ Longitude.GetHashCode()在反转Latitude和Longitude时给出相同的结果。所以这不是一个好的解决方案,因为我想确保coord(x,y)!= coord(y,x); 由于操作的顺序很重要,您的代码可以正常工作。 感谢精度,这有助于:) – 2010-02-18 08:45:44

2

存在过载到GrouBy 方法,其采用的IEqualityComparer 作为参数,但使用组子句是那里的 等效?

你总是可以通过匿名类型组,如果你只是想快速在线解决方案,不担心打的钥匙确切类型:

var grouped = 
    from it in items 
    group it by new {it.Coordinate.Latitude, it.Coordinate.Longitude}; 
+0

我知道这个解决方案,但你不会有坐标类作为关键,只是一个匿名类型。 – 2010-02-18 06:35:11

相关问题