2010-03-16 11 views
5

Beachten Sie, dass die _src IQueryable<U> erben und V new() erben;C# Linq Problem in Methodenkette auswählen

Ich schrieb die folgende Aussage, es gibt keinen Syntaxfehler.

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

Aber wenn i-RE schrieb es wie folgt, die Visual Studio-Editor einen Fehler in der "Select", klagt

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

Der Fehler ist:

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) 

Könnte jemand erklären, dieses Phänomen, und was ist die Lösung, um den Fehler zu beheben?

=== Edit (2010-03-16 05.35) ===

Dank Mike Zwei. Ich habe auch ein einfaches Beispiel wie Sie versucht. Es funktioniert, aber das tut nicht in meinem. Ich stellte den Code wie folgt:

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

Ich möchte die LeafNodes funktionieren in Linq Methode Kette Methode neu geschrieben werden. Irgendeine Idee?

+0

Dank IQueryable. Was ist die äquivalente Aussage des ersten? – Gnought

+0

Der von Ihnen hinzugefügte Code wird nicht kompiliert, es sei denn, U ist ein Element mit einer Eigenschaft Right und Left. Es kann also nicht einfach ein 'IQueryable ' sein, es sei denn, es gibt ein 'wo U: ILeftRight' oder so etwas. –

+0

Ich habe es dank Ihrer aktualisierten Probe herausgefunden. Siehe aktualisierte Antwort unten. Danke für die Bereitstellung weiterer Informationen. –

Antwort

1

Was ist der Typ von _src? Wird IQueryable direkt implementiert? Ich frage, weil ich ein vereinfachtes Beispiel dafür bekommen kann, was Sie zeigen, um zu arbeiten.

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

Beide von denen wählt Arbeit für mich. Ich denke, wenn der Compiler weiß, dass ints (oder in Ihrem Fall _src) ein IQueryable ist, wird es die richtige Überladung aufrufen. Oder verpasse ich etwas völlig? Vielleicht habe ich es zu stark vereinfacht und ein paar Details verloren.

BEARBEITEN: Erweitern, um den neuen Beispielcode mit einigen Änderungen zu verwenden.

Der Trick ist, dass Queryable.Select eine Expression<Func<X, V>> nimmt und Enumerable.Select nimmt ein Func<X,V> So brauchen Sie nur Select

eine Expression Version zur Verfügung zu stellen oder aus dem ursprünglichen Code

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

Die Fehler occurres weil Compiler kann nicht wählen, welche Methoden Sie ausgeführt werden soll: Select Erweiterungsmethode für IEnumerable<T> oder Select Erweiterungsmethode für IQueryable<T>

1

Das Problem, das Sie in laufen ist, dass es zwei verschiedene Verwendungen für Select sind in Ihr zweites Beispiel, und Sie haben die entsprechende using-Anweisung, um zu beiden zu gelangen. Der Compiler kann aus dieser Anweisung nicht herausfinden, welche Sie verwenden möchten. Sie müssen entweder einen spezielleren Aufruf zum Auswählen oder Entfernen einer Verwendung verwenden, wenn sie nicht mehr benötigt wird, oder auf andere Weise klären, welche Sie verwenden möchten.

+0

Wenn ich "AsQueryable()" zur Auswahl wie folgt hinzufügen: IQueryable d = _src.Where (s => s.Right - 1 == s.Left) .AsQueryable(). Wählen Sie (s => new V()); Der Fehler ist auch der gleiche. – Gnought

0

das beheben Mehrdeutigkeit für den Compiler verwenden Sie die AsEnumerable() Funktion

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

Oder zuweisen alle

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

Aber dies würde IEnumerable anstelle von IQueryable zurückgeben. Was ist das Problem, ohne den Rückgabetyp zu ändern? – Gnought

+0

@Gnought Ich füge es dem bearbeiteten Post hinzu. – Cornelius

+0

Vielen Dank für Ihre Testversion. – Gnought