tags:

views:

4265

answers:

4

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!

+2  A: 

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

Anton Gogolev
+5  A: 

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)

Marc Gravell
The .values bit is what I needed really, so you get the answer. I have edited my question to clarify what I was going for
qui
Note that with Where you'd typically return IEnumerable<Image> etc - glad you got it sorted, though ;-p
Marc Gravell
Actually, it's not sorted! More to come...
qui
A: 

What exactly are you trying to find? The single image for which that predicate returns true? If so, you could use:

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

But the return type you originally specified really isn't appropriate - and this is an odd way to use a dictionary, too.

Jon Skeet
Yeah Jon, I meant to put "where" not single, I'm blaming monday here.
qui
+3  A: 

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()
David B
Indeed! I changed it to IEnumerable and that did the trick
qui