如何修复循环多余执行问题?实现rowList与rowsCmd单循环匹配
The problem with your current nested loops is that you're assigning every rowsCmd entry to every rowList entry—so each row in rowList ends up with the last value from rowsCmd, and you're doing far more iterations than needed. Instead, you want to pair each row in rowList with the corresponding row in rowsCmd one-to-one.
Here are two clean ways to do this:
1. Use LINQ's Zip Method (Simplest Approach)
The Zip method from LINQ lets you iterate over two sequences in parallel, pairing each element from the first sequence with the matching element from the second. This is perfect for your one-to-one assignment need.
First, make sure you have using System.Linq; at the top of your file. Then modify your loop like this:
private void CalculateDist() { var Unique= Cursor.GetFieldValue<int>("Unique"); var document = new HeadersRepository().Get(Unique); if (document == null) { return; } var rowsRepository = new RowsRepository(document); var rowList = rowsRepository.GetRows(); var cmd = SqlClient.Main.CreateCommand(string.Format( @"select DOC.Unique, DOC.Number from DOC where DOC.Unique =@Unique order by DOC.Number"), new { Unique }); var rowsCmd = cmd.ExecObjects(new { Unique= 0, Number= 0, }); // Use Zip to pair rows one-to-one foreach (var pair in rowList.Zip(rowsCmd, (row, cmdRow) => new { Row = row, CmdRow = cmdRow })) { pair.Row.Number = pair.CmdRow.Number; } }
This will iterate exactly min(rowList.Count, rowsCmd.Count) times—so if rowList has 2 rows and rowsCmd has 3, it will assign the first 2 rowsCmd entries to the 2 rowList rows, which matches your requirement of only 2 iterations.
2. Use a For Loop (For Explicit Control)
If you prefer more explicit control, or need to validate that the number of rows matches, convert both sequences to lists and use an index-based loop:
private void CalculateDist() { var Unique= Cursor.GetFieldValue<int>("Unique"); var document = new HeadersRepository().Get(Unique); if (document == null) { return; } var rowsRepository = new RowsRepository(document); var rowList = rowsRepository.GetRows().ToList(); // Convert to list for index access var cmd = SqlClient.Main.CreateCommand(string.Format( @"select DOC.Unique, DOC.Number from DOC where DOC.Unique =@Unique order by DOC.Number"), new { Unique }); var rowsCmdList = cmd.ExecObjects(new { Unique= 0, Number= 0, }).ToList(); // Convert to list // Optional: Validate row counts match if that's a requirement if (rowList.Count != rowsCmdList.Count) { // Handle mismatch—log an error, throw, or return early Console.WriteLine($"Row count mismatch: rowList has {rowList.Count}, rowsCmd has {rowsCmdList.Count}"); return; } // Iterate with index to assign corresponding rows for (int i = 0; i < rowList.Count; i++) { rowList[i].Number = rowsCmdList[i].Number; } }
This approach is great if you need to ensure the two collections have the same number of rows (you can add error handling for mismatches) or if you're working with non-enumerable collections that support index access.
Key Notes:
- Both approaches avoid the nested loop inefficiency and ensure each row in
rowListgets the correct corresponding value fromrowsCmd. - The
Zipmethod stops when either sequence runs out of elements—so if one is longer than the other, it only processes up to the shorter length. - If you expect
rowsCmdandrowListto always have the same number of rows, adding a count check (like in the for loop example) can help catch bugs early.
内容的提问来源于stack exchange,提问作者Evgeniy Bojenov

