ByulTaeng
ByulTaeng

Reputation: 1269

Type arguments error in LINQ extension method

I wrote a LINQ extension to join 2 tables

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())
                    });
        }

The compiler understand the extension well but when I try to write

var result = left.ToDetail(right, l => l.ID, r => r.ID, r => r.Key, r => r.Value, "Key");

I got the following error:

The type arguments for method .ToDetail(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable, System.Func, System.Func, System.Func, System.Func, string)' cannot be inferred from the usage. Try specifying the type arguments explicitly

Then I tried to remove the keyProperty and valueProperty parameters from the extension, it run well without any error. I don't know why, maybe the compiler confused and cannot determine the parameter with the same type?

Any helps would be appreciated!

Upvotes: 0

Views: 650

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243061

In your function declaration, you use the same function type for rightProperty, keyProperty and valueProperty arguments, so both of these functions should have a type Func<TRight, TKey>.

This means that when you call the function, the type of r.ID, r.Key and r.Value must be the same (so that the C# compiler can infer the TKey type parameter from these two). My guess is that in your example, at least one of these three is different (probably ID).

(Aside, since you're converting the result of valueSelector and keySelector to string using the ToString method, there is probably no reason why you need to use generic types - a function returning object should do the trick).

Upvotes: 1

Related Questions