Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何使用linq按自定义类型分组_.net_Linq_Group By - Fatal编程技术网

.net 如何使用linq按自定义类型分组

.net 如何使用linq按自定义类型分组,.net,linq,group-by,.net,Linq,Group By,我有这门课 public class Item { public Coordinate coordinate { get; set; } ... ... } 坐标的定义如下: public class Coordinate { public Coordinate(float latitude, float longitude) { Latitude = latitude;

我有这门课

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;
我认为如果我在坐标类中重写Equals,这是可能的:

如果必须通过 查询变量到另一个方法。 使用创建一个特殊类 自动实现的属性 键,然后覆盖相等项 和GetHashCode方法。你也可以 使用struct,在这种情况下,您不需要 我们必须严格遵守这些规定 方法。有关更多信息,请参见如何 to:实现一个不可变的类 具有自动实现的属性

等于坐标类的实现:

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());
}
[TestMethod]
公共作废分组依据2个不同坐标的项目2个分组()
{
var items=新列表
{
新项目{坐标=新坐标(10,10)},
新项目{坐标=新坐标(10,10)},
新项目{坐标=新坐标(12,10)},
};
var grouped=从项目中的它开始
按它分组,协调成g
选择g;
Assert.AreEqual(2,grouped.Count());
}
Groupby方法有一个重载,该重载将IEqualityComparer作为参数,但是否有使用group子句的等价项?
我做错什么了吗??有什么想法吗?

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

GetHashCode实现示例:

public override int GetHashCode()
{
    int hash = 23;
    hash = hash * 31 + Latitude.GetHashCode();
    hash = hash * 31 + Longitude.GetHashCode();
    return hash;
}
请注意,比较
float
值以获得精确的相等性总是有一定的风险——但我至少希望您的单元测试能够通过,因为它们没有执行任何计算

格劳比号超载了 方法,该方法接受IEqualityComparer 作为参数,但是否存在 使用group子句是否等效

如果您只需要一个快速的内联解决方案,并且不担心键入键的确切类型,则始终可以按匿名类型分组:

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

刚试过,这就是我错过的。非常感谢:)public override int GetHashCode(){return((int)Latitude*100)^((int)Longitude*100);}如果哈希代码就是这样做的,那么应该确保相等代码与之匹配-它们应该彼此一致。Latitude.GetHashCode()^Longitude.GetHashCode()在反转纬度和经度时给出相同的结果。所以这不是一个好的解决方案,因为我想确保coord(x,y)!=坐标(y,x);您的代码可以工作,因为操作顺序很重要。感谢您的精确性,这很有帮助:)我知道这个解决方案,但您不会将坐标类作为键,而是一个匿名类型。