Linq: Was ist der Unterschied zwischen Select und Where?


122

Die Methoden Selectund Wheresind in Linq verfügbar. Was sollte jeder Entwickler über diese beiden Methoden wissen? Zum Beispiel: wann man eins über dem anderen verwendet, welche Vorteile es hat, eines über dem anderen zu verwenden usw.


7
Ich denke nicht, dass diese Frage als CW markiert werden sollte, sie könnte möglicherweise eine endgültige Antwort haben.
Brandon

1
@Brandon Es ist nichts Falsches daran, etwas CW zu markieren, wenn es objektiv ist.
Rex M

@ Rex, ich stimme zu. Nur zu sagen, dass der Unterschied zwischen Select und Where eine endgültige Antwort hat und der zweite Teil der Frage wahrscheinlich auf allgemein akzeptierten Praktiken beruht. Ich habe nur darauf hingewiesen, falls das OP nicht sicher ist, ob es Dinge als CW markiert. Wenn er beabsichtigt hat, dass es CW ist, dann ist das in Ordnung für mich.
Brandon

6
Es ist viel falsch daran. CW ist nutzlos und wird immer mehr, wenn Leute Fragen völlig zufällig als CW
markieren

Antworten:


126

Wo

findet übereinstimmende Elemente und gibt nur diejenigen zurück, die übereinstimmen ( Filterung ).

-> rein IEnumerable<A>, IEnumerable<A>raus

Wählen

Gibt etwas für alle Elemente in der Quelle zurück ( Projektion / Transformation ). Das etwas könnte das Objekt selbst sein, ist aber normalerweise eine Art Projektion.

-> rein IEnumerable<A>, IEnumerable<B>raus


15
Selectgibt immer die gleiche Anzahl von Elementen in der Liste zurück (unabhängig von einer Filterbedingung, die Sie möglicherweise haben). Wherekann abhängig von Ihrer Filterbedingung weniger Elemente zurückgeben.
goku_da_master

Und hier ist ein MSDN-Beispiel von selectund hier ist eines fürwhere
yazanpro

Zumindest für mich, mit etwas Hintergrundwissen mit anderen Sprachen, hilft es, das zu denken Where == filterundSelect == map
bgusach

52

Select und Where sind zwei völlig unterschiedliche Operatoren, die auf IEnumerable s einwirken .

Der erste ist ein Projektionsoperator , während der letzte ein Restriktionsoperator ist .

Ein interessanter Weg, um einen Einblick in das Verhalten solcher Operatoren zu erhalten, besteht darin, einen Blick auf ihren "Funktionstyp" zu werfen.

  • Wählen Sie: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; Als Eingabe wird sowohl eine IEnumerable mit Elementen vom Typ T1 als auch eine Funktion verwendet, die Elemente vom Typ T1 in Elemente vom Typ T2 umwandelt. Die Ausgabe ist eine IEnumerable, die Elemente vom Typ T2 enthält.

    Daraus lässt sich leicht ableiten, dass dieser Operator seine Ausgabe erzeugt, indem er die Eingabefunktion auf jedes Element der Eingabe IEnumerable anwendet und die Ergebnisse in eine neue IEnumerable einschließt.

    Unter Verwendung einer mathematischen Notation nimmt es als Eingabe (a, b, c, ...): IEnumerable <T1> und f: T1 → T2 und erzeugt (f (a), f (b), f (c) , ...): IEnumerable <T2>

  • Wobei: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; Dieser verwendet eine IEnumerable, die Elemente vom Typ T1 und ein Prädikat für T1 enthält (dh eine Funktion, die ein boolesches Ergebnis für eine Eingabe vom Typ T1 erzeugt). Sie sehen, dass die Ausgabe auch eine IEnumerable ist, die Elemente vom Typ T1 enthält.

    Diesmal würde man vermuten, dass ein Element der Eingabe IEnumerable in der Ausgabe IEnumerable vorhanden sein wird, abhängig vom Ergebnis der Anwendung des Prädikats auf das Element. Wenn Sie die Semantik des Operatornamens hinzufügen, können Sie sicher sein, dass die Ausgabe IEnumerable erzeugt wird, indem Sie aus der Eingabe nur die Elemente entnehmen, die bei der Anwendung des Prädikats als wahr ausgewertet werden.

Leute mit funktionalem Programmierhintergrund denken normalerweise so. Sie können daraus ableiten (oder zumindest raten ...), was ein Operator tut, indem Sie nur seinen Typ betrachten!

Versuchen Sie als Übung, andere von LINQ auf IEnumerables eingeführte Operatoren zu betrachten und ihr Verhalten abzuleiten, bevor Sie sich die Dokumentation ansehen!


47

Sie sind verschieden:

Selectdreht sich alles um Transformation .

Wheredreht sich alles um das Filtern .


18

Select ordnet eine Aufzählung einer neuen Struktur zu. Wenn Sie eine Auswahl für eine IEnumerable durchführen, erhalten Sie ein Array mit der gleichen Anzahl von Elementen, jedoch einem anderen Typ, abhängig von der von Ihnen angegebenen Zuordnung. Wobei die IEnumerable so filtert, dass Sie eine Teilmenge der ursprünglichen IEnumerable erhalten.



7

Wenn Sie wissen, wie sie Where implementiert haben, und Erweiterungsmethoden auswählen, können Sie vorhersagen, was es tut ... Ich habe versucht, Where zu implementieren und Erweiterungsmethoden auszuwählen ... Sie können es sich ansehen ...

Wo Implementierung ::

public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{

    foreach ( var data in a )
    {
        //If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
        if ( Method.Invoke ( data ) )
        {
            yield return data;
        }
    }
}

Implementierung auswählen ::

public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
    foreach ( var item in a )
    {
        //Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
        yield return Method.Invoke ( item );
    }
}

Meine Implementierung funktioniert für jede Sammlung einwandfrei ... Sie unterscheidet sich jedoch von den von Microsoft implementierten Erweiterungsmethoden, da sie Ausdrucksbäume verwenden, um dieselbe zu implementieren.


1

Im Fall von Select it können Sie einer IEnumerable einer neuen Struktur zuordnen.

  A.Select(x=>new X{UID=x.uid, UNAME=x.uname}) 
  //input as [IEnumerable<A>] -------->  return output as [IEnumerable<X> ]

Wenn () als Filter für IEnumerable fungiert, wird das Ergebnis auf der Grundlage der where-Klausel zurückgegeben.

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.