为什么使用匿名类型工作并使用不在GroupBy中的显式类型?

Jim*_*Jim 9 c# linq linq-to-objects c#-4.0

我有一个问题,我希望组类型强类型,但如果我这样做不正确分组.看下面的代码......

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; }
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
3
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)

我希望结果是相同的,无论使用显式类型也不是,即应该只有一个组有3个项目而不是3组有1个项目.这里发生了什么?

更新 我添加了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
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
1
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)

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

Jar*_*Par 9

在第一个版本中,您将创建一个匿名类型,其中包含一个名为的属性GroupKey.C#中的匿名类型使用结构相等性,因此值的相等性归结为键的相等性.这使它们正确地组合在一起.

在第二种情况下,您使用的是名为的自定义类型GroupingKey.它似乎使用默认或引用相等.因此,没有一个实例被认为是相同的,因此它们被分成不同的组.