编辑3:改进了问题措辞和示例
我有以下使用分组的linq查询。分组和选择操作很复杂,因此我将其中一个选项抽象为一个方法,该方法对如何呈现数据做出一些选择。
我的查询在匿名组定义中正常工作,但是只要我将它输入到类中以便将其作为IGrouping对象传递给方法,它就会停止对结果进行分组。
public class TestController : Controller
{
public JsonResult ThisWorks()
{
var valueList = DataMocker.GetTestValues();
var group = from v in valueList.AsEnumerable()
where (v.Data != 0)
group v by new
{
Year = v.Fecha.Value.Year,
Trimester = string.Empty,
Month = v.Fecha.Value.Month,
Day = 0,
}
into g
select new SeriesDataPoint
{
y = g.OrderByDescending(obd => obd.Fecha)
.Select(obd => obd.Data.Value)
.FirstOrDefault(),
color = "black",
month = g.Key.Month,
year = g.Key.Year,
seriesName = "Test Series",
};
return Json(group, JsonRequestBehavior.AllowGet);
}
public JsonResult ThisDoesnt()
{
var valueList = DataMocker.GetTestValues();
var group = from v in valueList.AsEnumerable()
where (v.Data != 0)
group v by new Models.SeriesResultGroup
{
Year = v.Fecha.Value.Year,
Trimester = string.Empty,
Month = v.Fecha.Value.Month,
Day = 0,
}
into g
select new SeriesDataPoint
{
y = RenderDataPoint(valueList, g),
color = "black",
month = g.Key.Month,
year = g.Key.Year,
seriesName = "Test Series",
};
return Json(group, JsonRequestBehavior.AllowGet);
}
public static decimal? RenderDataPoint(List<Models.ValoresResultSet> valores, IGrouping<Models.SeriesResultGroup, Models.ValoresResultSet> group)
{
return group.OrderByDescending(obd => obd.Fecha)
.Select(obd => obd.Data.Value)
.FirstOrDefault();
}
}
答案 0 :(得分:2)
在第一种情况下,您按匿名类型分组,由编译器生成。此类型还生成了Equals和HashCode覆盖(您可以通过ildasm进行检查)。匿名类型的默认值Equals运行每个字段的相等比较器。我认为这是为了在这样的情况下使用。
在第二种情况下,您可以按自定义类型进行分组。由于它是引用类型,因此默认相等比较器按引用比较对象。因为在分组之前,您会生成一系列对象,每个对象都是唯一的。所以默认的相等检查认为它们不同。
解决方案是(选择任何):
struct
而不是class
小心,不要忘记实现HashCode。