Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda "cannot be inferred from the usage"

Tags:

c#

lambda

linq

I have the following dictionary declared:

private readonly Dictionary<int, Image> dictionary;

And I have a method, which is causing a compiler error:

    public IQueryable<Image> Find(Func<Image, bool> exp)
    {
        return  dictionary.Single(exp);
    }

The error i get is:

Error   1   The type arguments for method 'System.Linq.Enumerable.Single<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. C:\work\MSD-AIDS-Images\MSD-AIDS-Images-Test\TestImageRepository.cs 34  30  MSD-AIDS-Images-Test

I have tried googling around, I cant seem to find anything definitive as to what I am doing wrong

Edit - This is monday morning at work.

I meant to put "where", not single

Edit 2!

Ok, the code is now this:

public IQueryable<Image> Find(Func<Image, bool> exp)
{
    return dictionary.Values.Where(exp);
}

Now I get the following error:

Error   1   Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<MSD_AIDS_Images_Data.Image>' to 'System.Linq.IQueryable<MSD_AIDS_Images_Data.Image>'. An explicit conversion exists (are you missing a cast?)    C:\work\MSD-AIDS-Images\MSD-AIDS-Images-Test\TestImageRepository.cs 34  20  MSD-AIDS-Images-Test

As an FYI, the method there is for implementing an interface, the declaration for that is:

IQueryable<T> Find(Func<T, bool> exp);

This has got more complicated than it should be!

like image 442
Chris James Avatar asked Feb 09 '09 14:02

Chris James


3 Answers

What is it you are trying to do? For example, Single will return an instance of T, not an IQueryable<T> (and for objects, you should probably be using IEnumerable<T> anyway)...

It feels like you want:

public Image Find(Func<Image, bool> predicate)
{
    return dictionary.Values.Single(predicate);
}

Of course, you could do this globally as an extension method via something like:

(edit includes Where from question edit)

static class DictionaryExtensions
{
    public static TValue FindSingle<TKey, TValue>(
        this IDictionary<TKey, TValue> dictionary,
        Func<TValue, bool> predicate)
    {
        return dictionary.Values.Single(predicate);
    }
    public static IEnumerable<TValue> Find<TKey, TValue>(
        this IDictionary<TKey, TValue> dictionary,
        Func<TValue, bool> predicate)
    {
        return dictionary.Values.Where(predicate);
    }
}

(I'm not sure it is much harder for the caller to do this themselves, though)

like image 70
Marc Gravell Avatar answered Nov 14 '22 20:11

Marc Gravell


An explicit conversion exists (are you missing a cast?)

There are two Where methods, one on System.Linq.Enumerable (which it is using), and one on System.Linq.Queryable (which you think it should be using, according to that return type).

You need to do one of the following:

  • change the return type to IEnumerable<Image> - I recommend this!
  • change the method call to Queryable.Where(dictionary.Values.AsQueryable(), exp)
  • call AsQueryable()
like image 26
Amy B Avatar answered Nov 14 '22 19:11

Amy B


IDictionary<TKey, TValue> implements IEnumerable<KeyValuePair<TKey,TValue>>, so your Func should look more like Func<KeyValuePair<TKey,TValue>>.

like image 2
Anton Gogolev Avatar answered Nov 14 '22 20:11

Anton Gogolev