为什么使用匿名类型可以工作,而使用显式类型却不能在 GroupBy 中使用?

发布于 2024-12-14 07:26:19 字数 2941 浏览 0 评论 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; }
        }
    } 
}

输出:

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 给出的答案!

I have a problem where I want a group type to be strongly typed but if I do it doesn't group correctly. See the code below...

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; }
        }
    } 
}

The output:

1
3
Press any key to continue . . .

I would expect the result to be the same regardless of using an explicit type nor not i.e. should only be one group with 3 items not 3 groups with 1 item. What is going on here?

Update
I added an IEqualityComparer and it works now! See below:

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
        }
    } 
}

Output:

1
1
Press any key to continue . . .

This pretty much confirms the answer given by JaredPar!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北凤男飞 2024-12-21 07:26:19

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

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

In the first version you are creating an anonymous type with a single property named GroupKey. Anonymous types in C# use structural equality so the equality of the values comes down to the equality of the keys. This causes them to be properly grouped together.

In the second case you are using a custom type named GroupingKey. It appears this uses the default or referential equality. Hence none of the instances are considered equal and hence they get put into different groups.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文