此代码返回不同的值。 但是,我想要的是返回强类型集合而不是匿名类型

我有以下代码:

var foo = (from data in pivotedData.AsEnumerable() select new { Group = data.Field("Group_Number"), Study = data.Field("Study_Name") }).Distinct(); 

正如预期的那样,这将返回不同 但是,我想要的是返回强类型集合而不是匿名类型,所以当我这样做时:

 var foo = (from data in pivotedData.AsEnumerable() select new BarObject { Group = data.Field("Group_Number"), Study = data.Field("Study_Name") }).Distinct(); 

这不会返回不同的值,它会返回所有值。 有没有办法用实际对象做到这一点?

要使Distinct() (和许多其他LINQfunction)工作,要比较的类(在您的示例中为BarObject )必须实现实现Equals()GetHashCode() ,或者另外提供单独的IEqualityComparer作为Distinct()的参数Distinct()

许多LINQ方法利用GetHashCode()来提高性能,因为在内部它们将使用诸如Set类的东西来保存唯一项,这些项使用散列进行O(1)查找。 此外, GetHashCode()可以快速告诉您两个对象是否可能是等效的,哪些绝对不是 – 只要GetHashCode()当然正确实现。

因此,为了完整性,您应该在LINQ实现Equals()GetHashCode()中创建要比较的所有类,或者创建单独的IEqualityComparer实现。

要么像dlev建议或使用:

 var foo = (from data in pivotedData.AsEnumerable() select new BarObject { Group = data.Field("Group_Number"), Study = data.Field("Study_Name") }).GroupBy(x=>x.Group).Select(x=>x.FirstOrDefault()) 

查看更多信息http://blog.jordanterrell.com/post/LINQ-Distinct()-does-not-work-as-expected.aspx

您需要为BarObject重写EqualsGetHashCode ,因为EqualityComparer.Default是引用相等,除非您提供了EqualsGetHashCode覆盖(这是Enumerable.Distinct(this IEnumerable source)使用的)。 或者,您可以将IEqualityComparer传递给Enumerable.Distinct(this IEnumerable, IEqualityComparer)

看起来Distinct无法比较您的BarObject对象。 因此,它比较了它们的引用,它们当然彼此不同,即使它们具有相同的内容。

因此要么覆盖Equals方法,要么为Distinct提供自定义EqualityComparer。 记住在实现Equals时覆盖GetHashCode ,否则如果将对象放入字典或哈希表作为键(例如HashSet ),它将产生奇怪的结果。 它可能(不确切地知道)Distinct内部使用哈希集。

以下是GetHashCode的一系列良好实践。

你想使用带有比较器的Distinct()的另一个重载 。 然后,您可以实现自己的IEqualityComparer

试试这个:

 var foo = (from data in pivotedData.AsEnumerable().Distinct() select new BarObject { Group = data.Field("Group_Number"), Study = data.Field("Study_Name") }); 

应该如此简单:

 var foo = (from data in pivotedData.AsEnumerable() select new { Group = data.Field("Group_Number"), Study = data.Field("Study_Name") }).Distinct().Select(x => new BarObject { Group = x.Group, Study = x.Study });