我写了一个LINQ扩展来加入2个表
public static IEnumerable<ObjectDetail<TLeft, string>> ToDetail<TLeft, TRight, TKey>(this IEnumerable<TLeft> left, IEnumerable<TRight> right, Func<TLeft, TKey> leftProperty, Func<TRight, TKey> rightProperty, Func<TRight, TKey> keyProperty, Func<TRight, TKey> valueProperty, string keySelector)
{
return (from l in left
join r in right on leftProperty(l) equals rightProperty(r) into one
select new
{
l,
one
}).AsEnumerable().Select(q => new ObjectDetail<TLeft, string>
{
Item = q.l,
Meta = q.one.Where(m => keySelector.Contains(keyProperty(m).ToString())).ToDictionary(m => keyProperty(m).ToString(), m => valueProperty(m).ToString())
});
}
编译器很好地理解扩展,但是当我尝试编写
时var result = left.ToDetail(right, l => l.ID, r => r.ID, r => r.Key, r => r.Value, "Key");
我收到以下错误:
方法的类型参数 .ToDetail(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable, System.Func, System.Func, System.Func, System.Func,string)' 无法从使用中推断出来。尝试 指定类型参数 明确地
然后我尝试从扩展中删除keyProperty和valueProperty参数,它运行良好,没有任何错误。我不知道为什么,也许编译器混淆了,无法确定具有相同类型的参数?
任何帮助都将不胜感激!
答案 0 :(得分:1)
在函数声明中,对rightProperty
,keyProperty
和valueProperty
参数使用相同的函数类型,因此这两个函数都应该具有类型Func<TRight, TKey>
。
这意味着当您调用该函数时,r.ID
,r.Key
和r.Value
的类型必须相同(以便C#编译器可以推断出TKey
从这两个类型参数)。我的猜测是,在你的例子中,这三个中至少有一个是不同的(可能是ID
)。
(除此之外,由于您使用valueSelector
方法将keySelector
和ToString
的结果转换为字符串,因此您可能无需使用泛型类型 - a函数返回object
应该可以解决问题。)