如何用LINQ简化嵌套属性批量更新方法?现有代码求优化
Hey there! Let's tackle simplifying your ReplaceNameInHistoryForPublisher method using LINQ, while also fixing a subtle bug in your original code and making the logic more readable.
First, a quick heads-up: your original code has a small issue— the iTotal variable isn't reset to 0 for each DutyAssignmentEntry iteration. That means if you have multiple entries with replacements, you'll overcount (e.g., first entry replaces 2, second replaces 3, your code would add 2 then 5 to the total instead of 2 then 3). The LINQ approach naturally avoids this problem.
Here's the optimized version:
public int ReplaceNameInHistoryForPublisher(string oldName, string newName) { try { // Sum up replacements across all entries while updating names return _DutyAssignments.Sum(entry => { // Get all assignments that need their name updated (store to avoid re-filtering) var assignmentsToUpdate = entry.Assignments.Where(a => a.Name == oldName).ToList(); // Update each matching assignment's name assignmentsToUpdate.ForEach(a => a.Name = newName); // Return the count of replacements for this entry to add to the total return assignmentsToUpdate.Count; }); } catch (Exception ex) { SimpleLog.Log(ex); return 0; } }
What's improved here:
- Cleaner counting: We use
Sum()to automatically tally up replacements across all entries, eliminating the need for manual counter variables likeiTotalandiTotalReplaced. - Clear intent:
Where()explicitly selects only the assignments matching the old name, making the code's purpose immediately obvious. - Removed redundancy: Since
DutyAssignmentEntryis almost certainly a reference type, modifying itsAssignmentscollection directly updates the object in your original_DutyAssignmentslist—so we can ditch the unnecessary_DutyAssignments[i] = oEntryline. - Bug fixed: Each entry's replacement count is calculated independently, so we don't carry over counts from previous entries like the original code did.
If you prefer an even more concise (still readable) version, you can combine the counting and update steps (note: this filters twice, which is negligible unless working with extremely large collections):
public int ReplaceNameInHistoryForPublisher(string oldName, string newName) { try { return _DutyAssignments.Sum(entry => { int count = entry.Assignments.Count(a => a.Name == oldName); entry.Assignments.Where(a => a.Name == oldName).ToList().ForEach(a => a.Name = newName); return count; }); } catch (Exception ex) { SimpleLog.Log(ex); return 0; } }
内容的提问来源于stack exchange,提问作者Andrew Truckle

