Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Linq Select Problem in Method Chain

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?

like image 716
Gnought Avatar asked Oct 25 '22 18:10

Gnought


2 Answers

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);
like image 103
Mike Two Avatar answered Nov 12 '22 20:11

Mike Two


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>

like image 45
Andrew Bezzub Avatar answered Nov 12 '22 20:11

Andrew Bezzub