2013-05-01 4 views
6

わかりやすい構文や便利な機能のためにLINQ文が大好きです。しかし、時々デバッグするのは非常に面倒です。具体的には、コレクションでLINQステートメントを実行し、コレクション内の要素の1つで例外が発生した場合、どのような問題が入力されたのか、どこから問題が発生したのかを把握するにはどうすればよいですか?このため、要素単位でのLINQのデバッグ

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

今:

0.46578 
12.314213 
1.444876 
... 

私はList<string>としてこれを読んで、より具体的なデータ構造にロードしています:

することは、私が1000の実数でテキストファイルを持っている想像してみて特定の入力、私は慎重にそれを見て気にしなかったし、それは876行が含まれていることが判明した(行番号が示されている):

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

何らかの理由で(おそらく、ファイルが誤動作したスクリプトによって生成された)。私のLINQメソッドチェーンは、もちろん例外をスローします。問題は、リストのどの要素が例外を引き起こしたのか、その値はどうだったのでしょうか?

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

すると例外がdouble.Parseを呼び出して文字列をハイライトだろう、と私は簡単に何を問題の入力を参照してくださいrowの上にマウスのことができるようになります。代わりに私はforループを使用する場合、明確にする

ありました。

もちろん、Resharperを使用してLINQ文をfor-loopsに変換してからデバッグすることはできますが、より良い方法がありますか?

+0

これは、LINQのどのようなEAP? EFまたはLINQ to SQL? –

答えて

3

ラムダ関数に条件付きブレークポイントを設定します。条件はs.StartsWith( "5.56")です。ラムダにカーソルを置いてF9を押すだけです。あなたはビジュアルスタジオを使用していると仮定します。

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

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

私はちょうど個人的にtryparseを使用します。

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

AppendTextAddNewLineは

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

編集

WriteDataToTextboxがに出IEnumerble<T>を書き込み、汎用的な方法であり、単に私がコンセプトのテストプログラムの私の小さな証拠のために書いた拡張メソッドでありますテキストボックス

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

出力をここに入れるのを忘れてしまったので、私はそれを行うべきです。これは、不良データのインデックスと、問題の原因となったデータそのものを示しています。

Good Data: 
0.46578 
12.314213 
1.444876 


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

あなたのコメントの建設的な性質のためによく感謝します。あなたがより良い方法を持っているので、あなたが "これまでに見た中で最も悪いLINQの使用法"ではないあなた自身の答えを投稿するほど親切になるでしょう。 – Charles380

+0

ここでの主な問題は、あなたの解が 'data + 2 + I'回の繰り返しであるという事実です。' I'は間違った行の数です - 'IndexOf'は、呼び出されるたびにコレクションを始めから繰り返す。すべての行を少なくとも2回 '' Parse'し、その大部分を3回(良い値の場合は2つの 'TryParse'と' Parse')します。それは本当に効率的ではありませんか?私は自分の答えを掲示した、それを批判する自由を感じる! – MarcinJuraszek

+0

私はあなたのコメントから非効率的な部分を除いてコードをより効率的にすることができるときに、どのようにコメントを書くのかを教えてください。 "あなたのソリューションは、データが2回以上繰り返されたとき、私は間違った行の数です - IndexOfは呼び出されるたびに最初からコレクションを繰り返します。また、すべての行を少なくとも2回解析し、そのほとんどを3回(TryParseと良い値を解析する)既にインデックスが提供されているオーバーロードを選択している。.Select((s、i)=> iがindexOf " – Charles380

0

私はなぜあなたがここにforeachループを好きではないわかりません。とにかくLINQはそれを内部的に使用しています.LINQを使用していくつかの長所と短所があり、デバッグは短所の1つです。

私はおそらくforeachでLINQをミックスし、次で終わるでしょう:

// 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 
} 

すべての例外を防ぐことができますし、すべての誤った値のためにあなたの行番号を与えること。 file_contentsを1回だけ繰り返し、すべての値が1回だけ解析されます。

1

免責事項:私は、LINQのデバッグは、Visual Studioを使用してハードボーダーラインは不可能である

OzCodeのために働きます。 OzCodeを試してみることをお勧めします。

これは、デバッグ時にコードがどのように表示されるか(6番目の項目の例外)です。そして、最後の1以来の例外をトリガ - - それは問題のある値を見つけるのは簡単だあなたは選択句に渡されたWHERE項目を調査することによって、例外の原因となったアイテム伝えることができ Debugging LINQ exception

あなたがOzCodeのLINQのデバッグを試すことができます興味があれば - 私達はちょうど始めた