2014-12-11 3 views
7

Ich war auf den Quellcode von Batch Methode suchen, und ich habe gesehen:Was ist der Zweck der Verwendung von Select (x => x) in einer Batch-Methode?

// Select is necessary so bucket contents are streamed too 
yield return resultSelector(bucket.Select(x => x)); 

Es gibt einen Kommentar, ich verstehe nicht ganz. Ich habe diese Methode ohne Select getestet und es hat gut funktioniert. Aber es scheint, dass es etwas gibt, das ich vermisse. Ich kann mir kein Beispiel vorstellen, wo das nötig wäre. Also, was ist der eigentliche Zweck der Verwendung von Select(x => x) hier?

Hier ist der vollständige Quellcode Referenz:

private static IEnumerable<TResult> BatchImpl<TSource, TResult>(
     this IEnumerable<TSource> source, 
     int size, 
     Func<IEnumerable<TSource>, TResult> resultSelector) 
    { 
     TSource[] bucket = null; 
     var count = 0; 

     foreach (var item in source) 
     { 
      if (bucket == null) 
       bucket = new TSource[size]; 

      bucket[count++] = item; 

      // The bucket is fully buffered before it's yielded 
      if (count != size) 
       continue; 

      // Select is necessary so bucket contents are streamed too 
      yield return resultSelector(bucket.Select(x => x)); 

      bucket = null; 
      count = 0; 
     } 

     // Return the last bucket with all remaining elements 
     if (bucket != null && count > 0) 
      yield return resultSelector(bucket.Take(count)); 
    } 
+0

Verzögerte Ausführung. Auf den Iterator wird erst zugegriffen, wenn er überzählig ist. –

+7

Das war wahrscheinlich mein Code, mit dem ich anfangen sollte. Hmm.Normalerweise würde ich dies tun, um zu verhindern, dass ein Result Selector die Quelle in ein Array umwandelt und dann damit herumhantiert, aber in diesem Fall wäre das eigentlich nicht schädlich. –

+1

@BradChristie Es wird auch ohne das 'Select' hier verzögert (was auch immer du meinst). – BartoszKP

Antwort

5

Um es zusammenzufassen, was in den Kommentaren ist, theoretisch ist dies überflüssig. Eine verzögerte Ausführung ist in diesem Fall nicht relevant. Am Punkt der yield voll Ausführung ist bereits gemacht: Inhalt bucket ist bereits berechnet und es gibt nichts zu verschieben.

Es gibt auch kein Problem, durch das Iteratorblock Verhalten verursacht - jedes Mal, wenn wir in dieser Implementierung sind wieder die bucket zurückgesetzt und neu erstellt wird (bucket = null unmittelbar nach yield). Selbst wenn jemand das Ergebnis in den Array-Typ umwandeln und modifizieren würde, ist uns das egal.

Ein Vorteil dieses Ansatzes scheint nur Eleganz zu sein: Es gibt eine Art Konsistenz zwischen allen Anrufen zu resultSelector ist. Ohne die „redundant“ Select, würde der tatsächliche Typ TSource[] die meiste Zeit war, und IEnumerable<TSource> für die hinteren Elemente, die die ganzen bucket nicht ausfüllte.

Allerdings kann man sich folgendes Szenario vorstellen:

  1. jemand mit dieser Funktion merkt, dass der tatsächliche Typ ist ein Array
  2. wegen einiger Drang zur Verbesserung der Leistung benötigen, werfen sie die empfangene Charge TSource[] (zB können sie nun Elemente überspringen effiziente, as Skip is not optimized for arrays)
  3. sie die Methode ohne Probleme, weil es, dass Count() % size == 0 in ihrem Fall geschieht
später 10

Bis, passiert es, dass ein zusätzlichen Elemente in springen, so dass die letzten yield ausgeführt werden. Und jetzt wird die Besetzung zu TSource[] fehlschlagen.

Also würde sich die Methode je nach Anzahl der Elemente und size in Bezug auf ihren Ergebnistyp (übergeben an den gegebenen Callback) inkonsistent verhalten. Man kann sich andere aufwendige Szenarien vorstellen, in denen diese Inkonsistenz Probleme verursachen kann, wie etwa ein ORM, das Objekte je nach Typ in verschiedene Tabellen serialisiert. In diesem Kontext würden Datenstücke in verschiedenen Tabellen enden.

Diese Szenarien basieren natürlich alle auf einem anderen Fehler und beweisen nicht, dass ohne die Select die Implementierung falsch ist. Es ist jedoch mehr freundlich mit den Select, in gewissem Sinne, dass sie die Anzahl solcher unglücklichen Szenarien auf ein Minimum reduziert.

Verwandte Themen