2013-05-01 10 views
6

Ich liebe LINQ-Anweisungen für die expressive Syntax und andere praktische Funktionen. Allerdings finde ich es sehr mühsam, sie manchmal zu debuggen. Insbesondere, wenn ich eine LINQ-Anweisung für eine Auflistung ausführen und eines der Elemente in der Auflistung eine Ausnahme verursacht, wie kann ich herausfinden, was die Problemeingabe war und wo das Problem herkam?Debuggen von LINQ pro Element

Stellen Sie sich vor ich eine Textdatei mit 1000 reellen Zahlen haben:

0.46578 
12.314213 
1.444876 
... 

ich dies als List<string> lese und es in eine bestimmte Datenstruktur laden:

var file_contents = File.ReadAllLines("myfile.txt"); 
var data = file_contents.Select(s => double.Parse(s)); 

Nun, für diese bestimmter Eingang, ich habe nicht die Mühe sorgfältig um es zu betrachten, und es stellt sich heraus, die 876. Zeile enthält (Zeilennummern angezeigt):

875 5.56786450 
876 Error: Could not calculate value. 
878 0.0316213 

Aus welchem ​​Grund auch immer (vielleicht wurde die Datei von einem Skript erzeugt, das fehlfunktionierte). Meine LINQ-Methodenkette wird natürlich eine Ausnahme auslösen. Das Problem ist, wie kann ich herausfinden, welches Element der Liste die Ausnahme verursacht hat und welchen Wert es hatte?

Um zu klären, ob stattdessen benutzte ich eine for-Schleife:

var data = new List<double>(); 
foreach(var row in file_contents) 
{ 
    var d = double.Parse(row); 
    data.Add(d); 
} 

Dann würde markieren die Ausnahme die Zeichenfolge, die double.Parse nennt, und ich möchte die Maus über row der Lage sein, leicht zu sehen, was das Problem Eingangs war.

Ich kann natürlich Resharper verwenden, um meine LINQ-Anweisungen in for-Schleifen zu konvertieren und sie dann zu debuggen, aber gibt es einen besseren Weg?

+0

Was für eine Art von LINQ gestartet ist das? EF oder LINQ zu SQL? –

Antwort

3

Setzen Sie einen bedingten Haltepunkt auf die Lambda-Funktion, wo die Bedingung ist am StartsWith ("5.56"). Sie müssen nur den Cursor auf das Lambda und drücken Sie F9. Angenommen, Sie verwenden Visual Studio.

2
var data = file_contents.Select(s => { 
    try 
    { 
     return double.Parse(s); 

    } 
    catch 
    { 
     throw; //breakpoint? 
    } 
}); 
0

Ich würde nur eine tryparse persönlich verwenden.

 var data = new List<string> 
      { 
       "0.46578", 
       "12.314213", 
       "Error: Could not calculate value.", 
       "1.444876", 
      }; 
     double d; 
     var good = data.Where(s => Double.TryParse(s, out d)).Select(Double.Parse); 
     var bad = data.Where(s => !Double.TryParse(s, out d)).Select(x => new 
      { 
       key = data.IndexOf(x), 
       value = x 
      }).ToDictionary(x => x.key, x => x.value); 


     textBox1.AppendTextAddNewLine("Good Data:"); 
     WriteDataToTextBox(good); 

     textBox1.AppendTextAddNewLine(String.Format("{0}{0}Bad Data:", Environment.NewLine)); 
     WriteDataToTextBox(bad); 

Die AppendTextAddNewLine ist einfach eine Erweiterung Methode, die ich für mein kleines Proof of Concept Prüfprogramm

public static void AppendTextAddNewLine(this TextBox textBox, string textToAppend) 
    { 
     textBox.AppendText(textToAppend + Environment.NewLine); 
    } 

bearbeiten

Die WriteDataToTextbox schrieb eine generische Methode ist, die eine IEnumerble<T> heraus schreibt das Textfeld

void WriteDataToTextBox<T>(IEnumerable<T> data) 
    { 
     foreach (var row in data) 
     { 
      textBox1.AppendTextAddNewLine(row.ToString()); 
     } 
    } 

Vergessen Sie, um die Ausgabe hier zu setzen, so denke ich, dass ich das tun sollte. Es zeigt den Index der fehlerhaften Daten und die Daten selbst, die das Problem verursacht haben.

Good Data: 
0.46578 
12.314213 
1.444876 


Bad Data: 
[2, Error: Could not calculate value.] 
+0

Vielen Dank für die konstruktive Art Ihres Kommentars. Da Sie einen besseren Weg haben, würden Sie so freundlich sein, Ihre eigene Antwort zu veröffentlichen, die nicht "die schlechteste LINQ-Nutzung ist, die Sie je gesehen haben". – Charles380

+0

Hauptproblem hier ist eine Tatsache, dass Ihre Lösung über "Daten" '2 + I'-Zeiten iterierte, wobei" I "die Anzahl der falschen Zeilen ist -" IndexOf "iteriert die Sammlung von Anfang an jedes Mal, wenn sie aufgerufen wird. Sie "pars" jede Zeile mindestens zweimal, und die meisten von ihnen dreimal (zwei 'TryParse' und eine' Parse' für gute Werte). Das ist nicht wirklich effizient, oder? Ich habe meine Antwort gepostet, fühlen Sie sich frei, es zu kritisieren! – MarcinJuraszek

+0

Lassen Sie mich Ihnen nur zeigen, wie ich einen Kommentar schreiben würde, wenn Code effizienter aus Ihren Kommentaren genommen werden könnte, ohne die nicht-konstruktiven Teile. "Ihre Lösung iterierte über Daten 2 + I mal, wobei I die Anzahl der falschen Zeilen ist - IndexOf wiederholt die Auflistung von Anfang an, wenn sie aufgerufen wird. Sie parsen auch jede Zeile mindestens zweimal und die meisten von ihnen dreimal (zwei Tryparse und eine Parsen für gute Werte). Es gibt bereits Select-Überladung mit einem gelieferten Index .. mit .Select ((s, i) => i ist der indexOf " – Charles380

0

Ich bin mir nicht sicher, warum Sie nicht foreach Schleife mögen hier. LINQ verwendet es intern ohnehin, und wie Sie bereits erkannt haben, gibt es einige Vor- und Nachteile der Verwendung von LINQ und Debugging ist eine der Nachteile.

Ich würde wahrscheinlich LINQ mischen mit foreach und am Ende mit folgenden:

// read all lines from file // 
var file_contents = File.ReadAllLines("myfile.txt"); 

// set initial data list length to number of lines for better performance 
var data = new List<double>(file_contents.Length); 

// list for incorrect line numbers 
var incorrectRows = new List<int>(); 

foreach (var x in file_contents.Select((s, i) => new {s, i})) 
{ 
    // x.s - line string 
    // x.i - line number 

    double value; 
    if (double.TryParse(x.s, out value)) 
     data.Add(value);  // add value, which was OK 
    else 
     incorrectRows.Add(x.i); // add index of incorrect value 
} 

, dass eine Ausnahme überhaupt vermieden werden und geben Sie Zahlen für alle falsche Werte auskleiden. Es iteriert auch nur einmal über file_contents und jeder Wert wird nur einmal analysiert.

1

Haftungsausschluss: Ich arbeite für OzCode

LINQ Debuggen schwer Borderline unmöglich mit Visual Studio ist. Ich schlage vor, Sie versuchen, OzCode zu verwenden.

Dies ist, was Ihr Code beim Debuggen aussieht (die Ausnahme in der 6. Element). Debugging LINQ exception

Sie können sagen, welche Artikel die Ausnahme verursacht durch die Elemente zu untersuchen, die der Select Klausel übergeben, wo - und seit dem letzten löste die Ausnahme - es ist einfach der säumige Wert zu finden.

Wenn Sie interessiert Sie OzCode LINQ Debuggen versuchen können - wir haben gerade ein EAP

Verwandte Themen