【问题标题】:Why does using anonymous type work and using an explicit type not in a GroupBy?为什么使用匿名类型有效而使用不在 GroupBy 中的显式类型?
【发布时间】:2011-11-04 22:09:28
【问题描述】:

我有一个问题,我希望对一个组类型进行强类型化,但如果我这样做,它就不能正确分组。请看下面的代码...

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 个项目的组,而不是 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
        }
    } 
}

输出:

1
1
Press any key to continue . . .

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

【问题讨论】:

  • 如果您将第二个 groups 更改为不同的变量名,而不是使用 &lt;Foo, dynamic&gt; 使用 &lt;Foo, GroupingKey&gt;,它会起作用吗?在这种情况下,断开连接可能是通用类型。
  • @Joel - 实际上动态的东西似乎并没有什么不同,直到我添加了 IEqualityComparer 并且它迫使我改变它以使类型对齐。

标签: c# linq c#-4.0 linq-to-objects


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多