2013-05-01 12 views
6

Etkileyici sözdizimi ve diğer kullanışlı özellikler için LINQ deyimlerini seviyorum. Ancak, bazen bunları ayıklamak çok zahmetli buluyorum. Özellikle, bir koleksiyon üzerinde bir LINQ ifadesi çalıştırdığımda ve koleksiyondaki öğelerden biri bir istisna oluşturduğunda, sorunun nedeninin ne olduğunu ve sorunun nereden geldiğini nasıl anlayabilirim? Bunun için,LINQ öğesi başına hata ayıklama

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

Şimdi:

0.46578 
12.314213 
1.444876 
... 

Ben List<string> olarak bu okuma ve daha özel bir veri yapısı içine yüklenmeden ediyorum:

Ben 1000 gerçek sayılar içeren bir metin dosyası var düşünün belirli girdi, dikkatlice bakma zahmetine girmedim ve 876. satırın ortaya çıktığı ortaya çıkıyor (gösterilen satır numaraları):

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

Sebep ne olursa olsun (belki de dosya hatalı çalışan bir komut dosyası tarafından oluşturulmuştur). LINQ yöntem zincirim elbette bir istisna atar. Sorun şu ki, listenin hangi unsurunun istisnaya neden olduğunu ve değerinin ne olduğunu nasıl anlarım? bunun yerine kullanılırsa

, netleştirmek için bir for döngüsü:

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

Sonra istisna double.Parse çağıran dize vurgulamak istiyorum, ve kolay kolay sorun ne girdi görmek için row üzerinde fare mümkün olacaktır oldu.

Elbette LARL ifadelerimi for döngülere dönüştürmek için Resharper'ı kullanabilir ve daha sonra bunları ayıklayabilirim, ancak daha iyi bir yol var mı?

+0

bu LINQ Ne biçim bir EAP? SQL'e EF veya LINQ? –

cevap

3

Koşulun s.StartsWith ("5.56") olduğu lambda işlevine koşullu kesme noktası koyun. Sadece imlecinizi lambdaya almanız ve F9 tuşuna basmanız yeterlidir. Görsel stüdyosu kullandığınızı varsayalım.

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

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

Sadece bir tryparse kullanırım.

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

Düzenleme

WriteDataToTextbox dışarı bir IEnumerble<T> yazar jenerik yöntemdir sadece ben kavramı test programının benim küçük kanıtı için yazdığı bir uzantısı yöntemidir metin kutusu

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

Çıktıyı buraya koymayı unuttum, bu yüzden bunu yapmam gerektiğini anladım. Kötü verilere ait indeksi ve soruna neden olan verilerin kendisini gösterir.

Good Data: 
0.46578 
12.314213 
1.444876 


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

Yorumunuzun yapıcı doğası için teşekkürler. Daha iyi bir yönteme sahip olduğunuzdan, "gördüğünüz en kötü LINQ kullanımı" olmayan kendi cevabınızı yayınlayacak kadar naziksiniz. – Charles380

+0

Burada asıl sorun, çözümünüzün 'data' '2 + I' zamanlar üzerinde yinelendiği,' '' yanlış satırların sayısı '' olan 'IndexOf' 'isimli koleksiyonun her çağrıldığından itibaren başlangıcını yinelediği bir gerçektir. Ayrıca her satır en az iki kez, ve en çok üç kez (iki TryParse ve bir "Parse" iyi değerleri için) Parse. Bu gerçekten verimli değil, değil mi? Cevabımı gönderdim, eleştirmek için çekinmeyin! – MarcinJuraszek

+0

Kodun daha etkili bir şekilde yorumlarınızdan alındığında, yapıcı olmayan kısımlara yönlendirildiğinde, nasıl yorum yazacağımı göstereyim. "Çözümünüz 2 + 1 kez yinelendi, hatalı satır sayısıdır. - IndexOf, her seferinde başlangıcından itibaren koleksiyonu tekrarlar. Ayrıca, her satırı en az iki kez ve en çok üç kez (iki Tryparse ve bir İyi değerler için ayrıştırma) Zaten bir endeksle birlikte aşırı yük seçtiniz .. kullanarak .Select ((s, i) => indexOf olarak – Charles380

0

Burada neden foreach döngüsünü sevmediğinizden emin değilim. LINQ onu zaten kullanır ve zaten LINQ kullanmanın bazı eksileri ve eksileri olduğunu fark ettiğiniz gibi hata ayıklama da bir eksidir.

muhtemelen foreach ile LINQ karıştırın ve aşağıdaki ile sona ereceğini: hiç bir istisna önleyecektir ve verecektir

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

tüm yanlış değerler için numaralar hattı. Ayrıca file_contents üzerinden sadece bir kez yinelenir ve her değer yalnızca bir kez ayrıştırılır.

1

Yasal Uyarı: LINQ ayıklama Visual Studio kullanarak sert sınırda imkansız

OzCode için çalışıyorum. OzCode kullanmayı denemenizi öneririm.

Kodunuzun hata ayıklaması sırasında göründüğü budur (6. öğenin istisnası). ve sonuncusu beri istisna tetiklenen - - bu kusurlu değerini bulmak kolaydır Sen Seç maddesi geçirilen nerede öğeleri inceleyerek duruma neden olan madde söyleyebilir Debugging LINQ exception

.

Eğer OzCode en LINQ hata ayıklama deneyebilirsiniz ilgileniyorsanız - sadece başladık bir