2009-03-11 10 views
0

Ich bin neugierig darauf, wie der folgende Code funktioniert, besonders der Teil, der die Delegierten enthält, da ich neu bin. Gibt es auch Engpässe im Code, zum Beispiel wäre die Verwendung eines SortedDictionary besser als die Verwendung einer Liste und dann die Sortierung mit LINQ? Ok, hier ist der Code:Erläutern, wie Delegierte im folgenden Code arbeiten?

public class ColorManager 
{ 
    private List<ColorData> colorCodes = new List<ColorData>(); 

    public List<ColorData> ColorCodes 
    { 
     get 
     { 
      var sortList = from a in this.colorCodes 
          orderby a.colorCode ascending 
          select a; 

      return sortList.ToList(); 
     } 
    } 

    public void FillData(DataTable table) 
    { 
     for(int row = 0; row < table.Rows.Count; row++) 
     { 
      ColorData cData = new ColorData(); 
      string name = table.Rows[row]["Color"].ToString().Trim(); 

      if(!this.colorCodes.Exists(
       delegate(ColorData e) 
       { 
        return e.ColorCode == name; 
       })) 
      { 
       cData.Add(table.Rows[row]["Color"].ToString()); 
       this.colorCodes.Add(cData); 
      } 
      else 
      { 
       this.colorCodes.Find(
        delegate(ColorData e) 
        { 
         return e.ColorCode == name; 
        }).Count++; 
      } 
     } 
    } 
} 

Antwort

2

Ich bin neugierig darauf, wie der folgende Code funktioniert, vor allem der Teil, der die Delegierten enthält, da ich neu darin bin.

Nehmen Sie zuerst einen Blick auf diese ColorCodes Eigenschaftenaccessor:

 var sortList = from a in this.colorCodes 
         orderby a.colorCode ascending 
         select a; 

Es gibt eine Liste der alle Farbcodes (this.colorCodes) aufsteigend (...orderby a.colorCode ascending). Bisher einfach. Wie wäre es mit der feurigeren Methode FillData?

Zuerst werden wir eine Schleife über jede Zeile in dieser Tabelle:

for(int row = 0; row < table.Rows.Count; row++) 
    { 

Dann werden wir in der Color Spalte der aktuellen Zeile suchen.

 ColorData cData = new ColorData(); 
     string name = table.Rows[row]["Color"].ToString().Trim(); 

Wenn diese Spalte keine Übereinstimmung in unserer Liste des Farbcodes hat, diese if Bedingung wahr ist. Die Exists-Methode verwendet eine Funktion mit einem Argument, die ein bool zurückgibt, was dieser anonyme Delegat ist: eine Funktion mit einem Argument (ColorData e), die einen booleschen Wert (e.ColorCode == name) zurückgibt. Es wird negiert (!this.[...]), wenn also eine Übereinstimmung gefunden wird, ist die Bedingung falsch.

 if(!this.colorCodes.Exists(
      delegate(ColorData e) 
      { 
       return e.ColorCode == name; 
      })) 
     { 
      cData.Add(table.Rows[row]["Color"].ToString()); 
      this.colorCodes.Add(cData); 
     } 

Andernfalls, wenn eine Übereinstimmung vorliegt, finden Sie den Namen einer anderen anonymen Delegaten verwenden, und fügen Sie ein zu der Anzahl der Elemente dieser Farbe.

 else 
     { 
      this.colorCodes.Find(
       delegate(ColorData e) 
       { 
        return e.ColorCode == name; 
       }).Count++; 
     } 
    } 

Beachten Sie, dass dieser Code etwas ineffizient ist, da die zwei verschiedenen anonymen Delegierten das gleiche tun und geteilt werden könnten.

+0

Wie könnte es umgestaltet werden, so dass sie teilen würden? – Xaisoft

+0

Sie können eine anonyme Methode überall dort verwenden, wo ein Delegat erwartet wird. Versuchen Sie var matchThisColor = new Func (e => e.ColorCode == Name) ;. –

0

Es ist ein anonymer Delegat, der als Auswahlkriterien für die Suche Ausdruck dient. In Worten, wenn die Farbe gleich der Farbe ist, die durch den Namen angegeben wurde, wird True zurückgegeben und Find fügt dies zu dem IEnumerable hinzu, das generiert wird. Wenn es false zurückgibt, wird Find es nicht enthalten. Es kann kürzer geschrieben werden als

p => p.ColorCode == name 
0

Exists und Find sind generische Erweiterungsmethoden. Sie für jede Schleife über jedes Element in der Sammlung. Übergabe des Delegates an einen Parameter (definiert als "(ColorData e)") und Rückgabe eines Booleans.

0

Delegierten:

Die Delegierten werden in diesem Beispiel ein Func Verfahren. Im Grunde erstellen Sie eine Methode im laufenden Betrieb, die ein ColorData-Argument übernimmt und einen Bool-Wert zurückgibt.

Damit können Sie Ihre Exists() - und Find() -Aufrufe für jedes Mitglied Ihrer IEnumerable-Sammlung zum Prüfen und Filtern ausführen.

Was Sortiert Wörterbuch:

Ist dies der einzige Ort, den Sie es verwenden, würden Sie besser dran SortedDictionary verwenden, da man nicht ständig zurückgreifen würden. Gerade jetzt, jedes Mal, wenn Sie ColorCodes anrufen, greifen Sie zurück. Ein SortedDictionary würde ständig sortiert werden.

2

Eigentlich gibt es dort mehr Delegierte als Sie erwarten. Die LINQ-Abfrage:

 var sortList = from a in this.colorCodes 
         orderby a.colorCode ascending 
         select a; 

ist eigentlich:

var sortList = this.colorCodes.OrderBy(a => a.colorCode); 

, die (für LINQ-to-Objects) ist das gleiche wie:

var sortList = this.colorCodes.OrderBy(delegate (ColorData a) { 
    return a.colorCode; 
}) 

Dieses verwendet einen Delegaten das Element zu identifizieren Sortieren nach - dh "bei einer ColorData gebe ich dir den colorCode". Beachten Sie, dass viele select verwendet auch beinhalten einen Delegaten, aber nicht in diesem Fall (die triviale select a wird vom Compiler entfernt).

Im Code:

 if(!this.colorCodes.Exists(
      delegate(ColorData e) 
      { 
       return e.ColorCode == name; 
      })) 

wir ein Prädikat verwenden; "Bei einer ColorData sage ich Ihnen, ob es eine Übereinstimmung ist, indem Sie den Namen auf Gleichheit testen". Beachten Sie, dass name hier in den Delegaten "eingefangen" wird, was einige ziemlich komplexe Compiler-Tricks beinhaltet (ich werde sie nicht beschreiben).


Re Effizienzen; es ist schwer, sicher zu sein, aber vielleicht:

Dictionary<string, ColorData> items = new Dictionary<string, ColorData>(); 
    foreach(DataRow row in table.Rows) { 
     string name = row["Color"].ToString().Trim(); 
     ColorData cData; 
     if (items.TryGetValue(name, out cData)) { 
      cData.Count++; 
     } else { 
      cData.Add(name); 
      colorCodes.Add(cData); 
      items.Add(name, cData); 
     } 
    } 

Dies vermeidet viele Vervielfältigung und verwendet ein Wörterbuch Werte zu finden, anstatt ständig mit Contains/finden. In vielen Fällen könnte ein LINQ GroupBy geholfen haben, aber vielleicht nicht in diesem Fall.