views:

289

answers:

4

Note that the _src inherit IQueryable<U> and V inherit new();

I wrote the following statement, there is no syntax error.

IQueryable<V> a = from s in _src where (s.Right - 1 == s.Left) select new V();

But if i RE-wrote it as follows, the Visual Studio editor complains an error in the "Select"

IQueryable<V> d = _src.Where(s => s.Right - 1 == s.Left).Select(s=> new V());

The Error is:

The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly.
Candidates are:
  System.Collections.Generic.IEnumerable<V> Select<U,V>(this System.Collections.Generic.IEnumerable<U>, System.Func<U,V>) (in class Enumerable)
  System.Linq.IQueryable<V> Select<U,V>(this System.Linq.IQueryable<U>, System.Linq.Expressions.Expression<System.Func<U,V>>) (in class Queryable)

Could anyone explain this phenomenon, and what the solution is to fix the error?

=== Edit (2010-03-16 5:35pm) ===

Thanks Mike Two. I also tried a simple example like you. It works but this does not do in mine. I posted the code as follows:

public class NSM<U, V> where U : IQueryable<U> where V : new()  
  {
    private U _src;
    public NSM(U source) { _src = source; }
    public IQueryable<V> LeafNodes
    {
      get
        {
          return from s in _src where (s.Right - 1 == s.Left) select new V();
        }
    }
  }

I want the LeafNodes function to be rewritten into linq method chain method. Any Idea?

+1  A: 

The error occurres because compiler cannot choose what methods you want to be executed: Select extension method for IEnumerable<T> or Select extension method for IQueryable<T>

Andrew Bezzub
+1  A: 

The problem you are running into is that there are 2 different uses for Select in your second example, and you have the appropriate using statement to get to both of them. The compiler can not figure out from that statement which one you want to use. You either have to use a more specialized call to Select or remove a using if it is no longer needed, or in some other way clarify which one you want to use.

Adkins
If i add "AsQueryable()" to the Select as follows:IQueryable<V> d = _src.Where(s => s.Right - 1 == s.Left).AsQueryable().Select(s=> new V());The error also is the same.
Gnought
+1  A: 

What is the type of _src? Does it directly implement IQueryable? I ask because I can get a simplified example of what you are showing to work.

IQueryable< int > ints = Enumerable.Range( 4, 12 ).AsQueryable();

IQueryable< decimal > foo = from s in ints where s > 7 select s * 4.2m;

IQueryable< decimal > bar = ints.Where( s => s > 7 ).Select( s => s * 4.2m );

Both of those selects work for me. I think if the compiler knows that ints (or in your case _src) is an IQueryable then it will call the right overload. Or am I completely missing something? Perhaps I oversimplified it and lost a bit of detail.

EDIT: Extending this to use the new sample code with some changes.

The trick is that Queryable.Select takes an Expression<Func<X, V>> and Enumerable.Select takes a Func<X,V> So you just need to provide an Expression version to Select

public interface ILeftRight
{
    int Right { get;}
    int Left { get; }
}

public class NSM<X, U, V> where U : IQueryable<X> where X : ILeftRight where V : new()  
{
    private readonly U _src;
    public NSM(U source) { _src = source; }
    public IQueryable<V> LeafNodes
    {
        get
        {
            //return from s in _src where (s.Right - 1 == s.Left) select new V();
            Expression< Func< X, V > > expression = s => new V();
            return _src.Where( s => s.Right - 1 == s.Left ).Select( expression );
        }
    }
}

Or from the original code

Expression<Func<X,V>> expression = s => new V();
IQueryable<V> d = _src.Where(s => s.Right - 1 == s.Left).Select(expression);
Mike Two
A: 

To resolve the ambiguity for the compiler use the AsEnumerable() function

src.AsEnumerable().Select(s => new V());

Or to assign to IQueryable

IQueryable<V> x = src.AsEnumerable().Select(s => new V()).AsQueryable();
Cornelius
But this would return IEnumerable<V> rather than IQueryable<V>. What's the fix without changing the return type?
Gnought
@Gnought I add it to the edited the post.
Cornelius
@Cornelius, thanks your trial.
Gnought