2013-05-01 23 views
6

Tôi yêu các câu lệnh LINQ cho cú pháp biểu cảm và các tính năng tiện lợi khác. Tuy nhiên, đôi khi tôi thấy rất phiền phức khi gỡ lỗi chúng. Cụ thể, khi tôi chạy một câu lệnh LINQ trên một bộ sưu tập và một trong các thành phần trong bộ sưu tập gây ra một ngoại lệ, làm thế nào tôi có thể tìm ra đầu vào của vấn đề là gì và vấn đề đến từ đâu?Gỡ lỗi LINQ trên cơ sở từng phần tử

Hãy tưởng tượng tôi có một tập tin văn bản với 1000 số thực:

0.46578 
12.314213 
1.444876 
... 

Tôi đang đọc bài viết này như một List<string> và tải nó vào một cấu trúc dữ liệu cụ thể hơn:

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

Bây giờ, cho điều này đầu vào cụ thể, tôi không quan tâm đến việc xem xét cẩn thận và nó chỉ ra dòng 876 chứa (số dòng được hiển thị):

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

Vì bất kỳ lý do nào (có thể tệp được tạo bởi tập lệnh bị trục trặc). Chuỗi phương pháp LINQ của tôi tất nhiên sẽ ném một ngoại lệ. Vấn đề là, làm thế nào để tôi tìm ra yếu tố nào của danh sách gây ra ngoại lệ, và giá trị của nó là gì?

Để làm rõ, nếu thay vào đó tôi sử dụng một cho vòng lặp:

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

Sau đó, ngoại trừ sẽ làm nổi bật các chuỗi trong đó kêu gọi double.Parse, và tôi sẽ có thể di chuyển chuột qua row để dễ dàng nhìn thấy những gì các vấn đề đầu vào là.

Tôi có thể, tất nhiên, sử dụng Resharper để chuyển đổi các câu lệnh LINQ của tôi thành các vòng lặp, sau đó gỡ lỗi chúng, nhưng có cách nào tốt hơn không?

+0

Loại LINQ nào? EF hoặc LINQ to SQL? –

Trả lời

3

Đặt điểm ngắt có điều kiện trên hàm lambda, trong đó điều kiện là s.StartsWith ("5.56"). Bạn chỉ cần có con trỏ của bạn trên lambda và nhấn F9. Giả sử bạn đang sử dụng studio trực quan.

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

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

Tôi sẽ chỉ sử dụng bản dùng thử riêng.

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

Các AppendTextAddNewLine chỉ đơn giản là một phương pháp mở rộng tôi đã viết cho bằng chứng nhỏ của tôi trong chương trình khái niệm kiểm tra

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

Sửa

Các WriteDataToTextbox là một phương pháp chung mà viết một IEnumerble<T> ra hộp văn bản.

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

Quên đưa kết quả vào đây để tôi hình tôi nên làm điều đó. Nó cho thấy chỉ số của dữ liệu xấu và chính dữ liệu gây ra sự cố.

Good Data: 
0.46578 
12.314213 
1.444876 


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

cũng nhờ tính chất mang tính xây dựng của nhận xét của bạn. Vì bạn có một cách tốt hơn, bạn sẽ được như vậy loại để gửi câu trả lời của riêng bạn mà không phải là "sử dụng LINQ tồi tệ nhất mà bạn từng thấy". – Charles380

+0

Vấn đề chính ở đây là một thực tế, rằng giải pháp của bạn lặp lại trên 'dữ liệu'' 2 + I' lần, trong đó 'I' là số hàng không chính xác -' IndexOf' lặp lại bộ sưu tập từ đầu mỗi khi nó được gọi. Bạn cũng 'Parse' mỗi dòng ít nhất hai lần, và hầu hết trong số họ ba lần (hai' TryParse' và một 'Parse' cho các giá trị tốt). Điều đó không thực sự hiệu quả, phải không? Tôi đã đăng câu trả lời của tôi, cảm thấy tự do để chỉ trích nó! – MarcinJuraszek

+0

Hãy để tôi chỉ cho bạn thấy làm thế nào tôi sẽ viết một bình luận khi mã có thể được thực hiện hiệu quả hơn lấy trực tiếp từ ý kiến ​​của bạn sans các phần không cấu trúc. "Giải pháp của bạn lặp đi lặp lại trên dữ liệu 2 + lần tôi, trong đó tôi là số hàng không chính xác - IndexOf lặp lại bộ sưu tập từ đầu mỗi khi nó được gọi. Bạn cũng Parse mỗi dòng ít nhất hai lần, và hầu hết trong số họ ba lần (hai TryParse và một Phân tích cú pháp cho các giá trị tốt) Đã có Chọn quá tải với chỉ mục được cung cấp .. sử dụng .Select ((s, i) => i là indexOf " – Charles380

0

Tôi không chắc tại sao bạn không thích foreach vòng lặp tại đây. LINQ sử dụng nó trong nội bộ anyway, và như bạn đã nhận ra có một số ưu và khuyết điểm của việc sử dụng LINQ và gỡ lỗi là một trong những khuyết điểm.

tôi có lẽ sẽ trộn LINQ với foreach và kết thúc với sau:

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

Điều đó sẽ ngăn chặn một ngoại lệ nào cả và sẽ cung cấp cho bạn hàng số lượng cho tất cả các giá trị không chính xác. Nó cũng lặp lại trên file_contents chỉ một lần và mọi giá trị đang được phân tích cú pháp chỉ một lần.

1

Disclaimer: Tôi làm việc cho OzCode

LINQ gỡ lỗi là ranh giới cứng không thể sử dụng Visual Studio. Tôi đề nghị bạn thử sử dụng OzCode.

Đây là mã của bạn trông khi gỡ lỗi (ngoại trừ trong mục thứ 6). Debugging LINQ exception

Bạn có thể biết được mục gây ra ngoại lệ bằng cách điều tra các mục mà nơi truyền cho Chọn khoản - và kể từ khi người cuối cùng gây ra một ngoại lệ - nó dễ dàng để tìm giá trị vi phạm.

Nếu bạn quan tâm, bạn có thể thử gỡ lỗi LINQ của OzCode - chúng tôi vừa mới bắt đầu EAP

Các vấn đề liên quan