为什么使用匿名类型可以工作,而使用显式类型却不能在 GroupBy 中使用?
我有一个问题,我希望组类型是强类型的,但如果我这样做,它就不能正确分组。请参阅下面的代码...
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在第一个版本中,您将创建一个带有名为
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.