So in things like GroupBy()
in Linq, you can provide an implementation of IEqualityComparer<T>
to help with object comparisons. It seems, though, that it would be easier to simply pass in a lambda expression.
Example:
// current implementation
myCollection.GroupBy(c => c.Foo, c => c.Bar, new FooBarComparer());
// it seems easier to...
myCollection.GroupBy(c => c.Foo, c => c.Bar, (x, y) => x.Baz == y.Baz);
Given a simple implementation of IEqualityComparer<T>
like this:
public class FooBarComparer : IEqualityComparer<FooBar> {
public bool Equals(FooBar x, FooBar y) {
return x.Baz == y.Baz;
}
public int GetHashCode(FooBar obj) {
return obj.GetHashCode();
}
}
It seems that providing a lambda expression could be just as effective. As it stands now, if I try to pass in an IEqualityComparer<T>
with a Linq query to a database, it fails because SQL Server (or whatever) doesn't know anything about my class. It seems that a lambda would be able to be translated into SQL that can be used in the target database.
Is there a specific reason this is not provided as an option in Linq?
答案 0 :(得分:0)
你需要两个lambdas,以便GetHashCode
也有一个等价物。除此之外,这可行,是的。有些LINQ方法不使用哈希码但使用相等(Enumerable.Contains
)。
我想这只是为了让整个BCL使用一个标准的API相等的API。您可以使用委托支持的比较器实现或将myComparer.Equals
转换为委托,轻松地在委托和比较器之间进行转换。
对于数据库的远程表达式,远程比较器表达式并不容易。 GROUP BY
在SQL中不支持。它肯定可以工作,但它是一个利基用例(实际上,如果GroupBy
的比较表达式不提供相等关系,我不确定在转换为SQL时会出现这种情况。)< / p>
答案 1 :(得分:0)
要提高效率GroupBy
/ Distinct
,您需要做两件事:
或者你可以遵循C ++路线
如果你只有一个相等比较器,那么GroupBy
的难度就像 O(n ^ 2),因为如果你有5个元素,你需要5 + 4 + 3 + 2 + 1比较,所以n *(n + 1)/ 2等15.这是一个好的&#34;图书馆不会允许你做(并且没有理智的SQL服务器会做!)
现在,显然LINQ库可以分析你的等式lambda,看看它是
(x, y) => x.Baz == y.Baz
看到它是对称的,所以左边的术语和右边的术语都是
形式x => x.Baz
并使用它来生成一个哈希并选择一个比较器。但在这一点上,直接做更容易
myCollection.GroupBy(c => c.Foo.Baz)
是的,你可以这样做: - )
然后,
myCollection.GroupBy(c => c.Foo.Baz, c => new { c.Foo, c.Bar })
.Select(c => new { Key = c.First().Foo, Values = c.Select(x => x.Bar) })
这与您的预期GroupBy
非常相似(唯一的区别是这些值位于Values
IEnumerable<>
)
现在......对于使用IEqualityComparer<T>
的重载...正如我在评论中写的那样,我认为它们应该与&#34; stock&#34;比较器,LINQ提供程序可以识别,如各种StringComparer.*
(例如StringComparer.OrdinalIgnoreCase
)和EqualityComparer<T>.Default
,代表&#34;默认&#34;比较器。