GroupBy 项目不相等

No equality on GroupBy item

我正在遍历 IGrouping 的可枚举并对每个条目执行相等性检查。但是,当逐步执行此代码时,我可以看到从未满足相等性检查。

namespace EqualityGroupingTest
{
    public class Reading
    {
        public int Id { get; set; }
        public string Label { get; set; }
        public int Measurement { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var readings = new List<Reading>()
            {
                new Reading() {Id = 1, Label = "A101", Measurement = 3},
                new Reading() {Id = 2, Label = "A101", Measurement = 5},
                new Reading() {Id = 3, Label = "A101", Measurement = 8},
                new Reading() {Id = 4, Label = "A102", Measurement = 2},
                new Reading() {Id = 5, Label = "A102", Measurement = 5},
                new Reading() {Id = 6, Label = "A102", Measurement = 9}
            };

            var offset = -1;
            var grouping = readings.GroupBy(i => i.Label);
            foreach (var group in grouping)
            {
                var range = (group.Last().Measurement - group.First().Measurement);

                if(group.Equals(grouping.Last()))
                {
                    range += offset;
                }
            }
        }
    }
}


从未遇到过检查我是否正在查看最后一个分组的代码。我可以更改此代码:

if(group.Equals(grouping.Last()))

收件人:

if(group.Key.Equals(grouping.Last().Key))

这解决了问题,但我不明白为什么不满足 IGrouping 的检查。我可以看到变量 groupgrouping.Last() 之间的哈希码在手表 window 中是不同的,但同样,我不确定这是为什么。如果有人可以澄清为什么会发生这种情况,我想知道吗?

因为 grouping 是一个延迟执行的 LINQ 查询,它在 grouping.Last() 处的循环中再次执行。这将创建内部 class Grouping 的新实例,因此 Object.ReferenceEquals 永远不会 returns true

您可以将它们添加到一个集合中,例如通过附加 ToList:

var grouping = readings.GroupBy(i => i.Label).ToList();

如果在documentation中发现"This method is implemented by using deferred execution"这句话要小心了。这意味着你得到的不是一个集合,而是一个 "query" ,如果你使用它,它将始终被执行(例如通过使用 foreach 循环,或非延迟方法,如 First/ LastToArray/ToList)。 但是,如果您附加其他延迟方法,如 SelectWhereOrderBy,它将不会被执行。那么你只是在构建最终的 query.