为什么在GroupBy中使用匿名类型和显式类型可以工作?

本文关键字:类型 工作 GroupBy 为什么 | 更新日期: 2023-09-27 18:13:38

我有一个问题,我想要一个强类型的组类型,但如果我这样做,它不会正确分组。请看下面的代码…

using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication35
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Foo> foos = new List<Foo>();
            foos.Add(new Foo() { Key = "Test" });
            foos.Add(new Foo() { Key = "Test" });
            foos.Add(new Foo() { Key = "Test" });
            var groups = foos.GroupBy<Foo, dynamic>(entry => new
            {
                GroupKey = entry.Key
            });
            Console.WriteLine(groups.Count());
            groups = foos.GroupBy<Foo, dynamic>(entry => new GroupingKey()
            {
                GroupKey = entry.Key
            });
            Console.WriteLine(groups.Count());
        }
        public class Foo
        {
            public string Key { get; set; }
        }
        public class GroupingKey
        {
            public string GroupKey { get; set; }
        }
    } 
}
输出:

1
3
Press any key to continue . . .

无论是否使用显式类型,我都希望结果是相同的,即应该只有一个包含3个项目的组,而不是包含1个项目的3个组。这是怎么回事?

更新 我添加了一个IEqualityComparer,它现在工作了!见下文:

using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication35
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Foo> foos = new List<Foo>();
            foos.Add(new Foo() { Key = "Test" });
            foos.Add(new Foo() { Key = "Test" });
            foos.Add(new Foo() { Key = "Test" });
            var groups = foos.GroupBy<Foo, dynamic>(entry => new //GroupingKey()
            {
                GroupKey = entry.Key
            });
            Console.WriteLine(groups.Count());
            groups = foos.GroupBy<Foo, GroupingKey>(entry => new GroupingKey()
            {
                GroupKey = entry.Key
            }, new GroupingKeyEqualityComparer());
            Console.WriteLine(groups.Count());
        }
        public class Foo
        {
            public string Key { get; set; }
        }
        public class GroupingKey
        {
            public string GroupKey { get; set; }              
        }
        public class GroupingKeyEqualityComparer : IEqualityComparer<GroupingKey>
        {
            #region IEqualityComparer<GroupingKey> Members
            public bool Equals(GroupingKey x, GroupingKey y)
            {
                return x.GroupKey == y.GroupKey;
            }
            public int GetHashCode(GroupingKey obj)
            {
                return obj.GroupKey.GetHashCode();
            }
            #endregion
        }
    } 
}
输出:

1
1
Press any key to continue . . .

这几乎证实了JaredPar给出的答案!

为什么在GroupBy中使用匿名类型和显式类型可以工作?

在第一个版本中,您正在创建一个具有单个属性GroupKey的匿名类型。c#中的匿名类型使用结构相等,因此值的相等归结为键的相等。这使得它们被正确地分组在一起。

在第二个例子中,您使用了一个名为GroupingKey的自定义类型。这似乎使用了默认或引用相等。因此,没有一个实例被认为是相等的,因此它们被放在不同的组中。