我发现这篇关于创建泛型的可爱博客文章IEqualityComparer
让您可以指定用于相等测试的 lambda 表达式。这对于使用标准查询运算符构建流畅 的连接表达式非常有帮助,如下例所示(有效的、自包含的LINQPad脚本;只需复制粘贴即可!):
void Main()
{
var outers = new [] {
Tuple.Create("a", "b"),
Tuple.Create("a", "c")
};
var inners = new [] {
Tuple.Create("b", "c"),
Tuple.Create("a", "c")
};
var j2s = outers
.Join(
inners,
outer => outer,
inner => inner,
(outer, inner) => Tuple.Create(outer, inner),
new GenericEqualityComparer<Tuple<string, string>>(
(u, v) => (u.Item1 == v.Item1 && u.Item2 == v.Item2))
)
.Dump("Using Custom Equality Comparer")
;
}
public sealed class GenericEqualityComparer<T> : IEqualityComparer<T>
{
internal Func<T, T, bool> EqualsFunc {get; private set;}
internal Func<T, int> GetHashCodeFunc {get; private set;}
public GenericEqualityComparer(
Func<T, T, bool> equalsFunc,
Func<T, int> getHashCodeFunc = null)
{
if (equalsFunc == null)
throw new ArgumentNullException("equalsFunc");
if (getHashCodeFunc == null)
getHashCodeFunc = (t => 0x1BADF00D);
EqualsFunc = equalsFunc;
GetHashCodeFunc = getHashCodeFunc;
}
public bool Equals(T x, T y)
{
return EqualsFunc(x, y);
}
public int GetHashCode(T obj)
{
return GetHashCodeFunc(obj);
}
}
问题是我怎样才能让这个东西使用类型推断?编译器强制要求明确地声明构造函数的类型参数GenericEqualityComparer<Tuple<string, string>>
,尽管我直觉地认为编译器应该能够弄清楚。如果我省略了显式类型参数,我会得到
Using the generic type 'UserQuery.GenericEqualityComparer<T>' requires 1 type arguments
如果没有类型推断,这似乎是一个更广泛的场景,比如使用匿名类型,如下所示,它是无望的:
var j3s = outers
.Join(
inners,
outer => new {Left = outer.Item1, Right = outer.Item2},
inner => new {X = inner.Item1, Y = inner.Item2},
(outer, inner) => Tuple.Create(outer, inner),
new GenericEqualityComparer<????????????????>(
(u, v) => (u.Left == v.X && u.Right == v.Y)
)
)
.Dump("Using type inference?")
;