6

表現力豊かな構文やその他の便利な機能を備えた LINQ ステートメントが大好きです。しかし、時々それらをデバッグするのは非常に面倒です。具体的には、コレクションに対して LINQ ステートメントを実行し、コレクション内の要素の 1 つが例外を引き起こした場合、問題の入力が何であり、どこから問題が発生したかをどのように把握できますか?

1000 の実数を含むテキスト ファイルがあるとします。

0.46578
12.314213
1.444876
...

これを として読み取りList<string>、より具体的なデータ構造にロードしています。

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

さて、この特定の入力について、私はそれを注意深く見ようとはしませんでした。

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

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

明確にするために、代わりに for ループを使用した場合:

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

次に、例外によって を呼び出す文字列が強調表示され、double.Parseマウス カーソルを合わせるrowと問題の入力が何であるかを簡単に確認できます。

もちろん、Resharper を使用して LINQ ステートメントを for ループに変換し、デバッグすることもできますが、もっと良い方法はありますか?

4

5 に答える 5

2

免責事項: 私は OzCode で働いています

LINQ のデバッグは、Visual Studio を使用して行うことはほぼ不可能です。OzCode を使ってみることをお勧めします。

これは、デバッグ時のコードの外観です (6 番目の項目の例外)。 LINQ 例外のデバッグ

Select句に渡されたアイテムを調査することで、例外の原因となったアイテムを特定できます。また、最後のアイテムが例外をトリガーしたため、問題のある値を簡単に見つけることができます。

興味がある場合は、OzCode の LINQ デバッグを試すことができます - EAPを開始したばかりです

于 2016-06-14T14:11:37.927 に答える
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.]
于 2013-05-01T15:51:26.473 に答える
0

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

私はおそらくLINQを混ぜforeachて、次のようになります:

// 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_contents1 回だけ反復し、すべての値が 1 回だけ解析されます。

于 2013-05-01T19:37:47.593 に答える