2010-03-16 19 views
5

Należy zauważyć, że dziedziczenie _src dziedziczy IQueryable<U> i dziedziczy po new();C# Linq Wybierz problem w łańcuchu metod

Napisałem następujące oświadczenie, nie ma błędu składni.

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

Ale jeśli re-pisze to w następujący sposób, edytor Visual Studio narzeka błąd w "Wybierz"

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

błędu jest:

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) 

Czy ktoś może wyjaśnić to zjawisko i jakie rozwiązanie polega na naprawieniu błędu?

=== Edit (2010-03-16 17:35) ===

Dzięki Mike Two. Próbowałem też prosty przykład jak ty. Działa, ale to nie działa w moim. Wysłałem kod w następujący sposób:

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

Chcę, aby funkcja LeafNodes została przepisana na metodę łańcucha metody linq. Dowolny pomysł?

+0

Dzięki wszystkim. Jakie jest równoważne stwierdzenie pierwszego? – Gnought

+0

Ten kod, który dodałeś, nie będzie się kompilował, chyba że U jest czymś, co ma właściwość Prawy i Lewy. Więc nie może to być po prostu 'IQueryable ' chyba że istnieje 'where U: ILeftRight' lub coś podobnego. –

+0

Wyjaśniałem to dzięki twojej zaktualizowanej próbce. Zobacz zaktualizowaną odpowiedź poniżej. Dziękuję za udzielenie dodatkowych informacji. –

Odpowiedz

1

Jaki jest typ _rrc? Czy to bezpośrednio implementuje IQueryable? Pytam, ponieważ mogę uzyskać uproszczony przykład tego, co pokazujesz, aby zadziałał.

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

Obie te selekcje działają dla mnie. Myślę, że jeśli kompilator wie, że ints (lub w twoim przypadku _src) jest IQueryable, to wywoła właściwe przeciążenie. Czy może zupełnie czegoś brakuje? Być może uprośniłem to i straciłem trochę szczegółów.

EDYCJA: Rozszerzenie tego, aby użyć nowego kodu przykładowego z pewnymi zmianami.

Sztuką jest to, że Queryable.Select bierze Expression<Func<X, V>> i Enumerable.Select trwa Func<X,V> więc wystarczy dostarczyć wersję Expression do Select

Albo z oryginalnego kodu

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

W occurres błąd, ponieważ kompilator nie może zdecydować, jakie metody chcesz być wykonywane: metodę Select przedłużający dla IEnumerable<T> lub Select metodę rozszerzenia dla IQueryable<T>

1

Problem jest uruchomiony na to, że istnieją 2 różne zastosowania dla wybranego w Twój drugi przykład, i masz odpowiednią instrukcję użycia, aby dostać się do obu z nich. Kompilator nie może dowiedzieć się z tego oświadczenia, którego z nich chcesz użyć. Musisz użyć bardziej specjalistycznego połączenia, aby wybrać lub usunąć użycie, jeśli nie jest już potrzebne, lub w inny sposób wyjaśnić, którego chcesz użyć.

+0

Jeśli dodaję "AsQueryable()" do opcji Wybierz w następujący sposób: IQueryable d = _src.W tym miejscu (s => s.Right - 1 == s.Left) .AsQueryable(). Wybierz (s => nowy V()); Błąd jest taki sam. – Gnought

0

aby rozwiązać niejednoznaczność kompilatora korzysta z funkcji AsEnumerable()

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

Albo przypisać do IQueryable

IQueryable<V> x = src.AsEnumerable().Select(s => new V()).AsQueryable(); 
+0

Ale to powrócił IEnumerable , a nie IQueryable . Jaka jest poprawka bez zmiany typu zwrotu? – Gnought

+0

@Gnought Dodaję go do edytowanego postu. – Cornelius

+0

dziękuję za proces. – Gnought