Reputation: 3659
Edit 3:Improved question wording and examples
I have the following linq query that uses grouping. The grouping and select operations are complex, so I abstracted one of the selects to a method that makes some choices on how to render the data.
My query works correctly inside the anonymous group definition, but as soon as I type it to a class in order to pass it to a method as an IGrouping object it stops grouping the results.
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();
}
}
Upvotes: 0
Views: 2059
Reputation: 2195
In first case you group by anonymous type, generated by compiler. This type also has generated Equals and HashCode overrides (you can check it via ildasm). Anonymous type`s default Equals runs equality comparer for each field. I think this was made for use in cases like this.
In second case you group by your custom type. Since it is a reference type, default equality comparer compares objects by reference. Because before grouping you produce a sequence of objects, each of them is unique. So default equality check thinks that they differs.
Solutions are (choose any):
struct
instead of class
Be careful and don`t forget to implement HashCode as well.
Upvotes: 2