Reputation: 29301
I would like to remove N items from an IList collection. Here's what I've got:
public void RemoveSubcomponentsByTemplate(int templateID, int countToRemove)
{
// TaskDeviceSubcomponents is an IList
var subcomponents = TaskDeviceSubcomponents.Where(tds => tds.TemplateID == templateID).ToList();
if (subcomponents.Count < countToRemove)
{
string message = string.Format("Attempted to remove more subcomponents than found. Found: {0}, attempted: {1}", subcomponents.Count, countToRemove);
throw new ApplicationException(message);
}
subcomponents.RemoveRange(0, countToRemove);
}
Unfortunately, this code does not work as advertised. TaskDeviceSubcomponents is an IList, so it doesn't have the RemoveRange method. So, I call .ToList() to instantiate an actual List, but this gives me a duplicate collection with references to the same collection items. This is no good because calling RemoveRange on subcomponents does not affect TaskDeviceSubcomponents.
Is there a simple way to achieve this? I'm just not seeing it.
Upvotes: 2
Views: 892
Reputation: 5439
Unfortunately, I think you need to remove each item individually. I would change your code to this:
public void RemoveSubcomponentsByTemplate(int templateID, int countToRemove)
{
// TaskDeviceSubcomponents is an IList
var subcomponents = TaskDeviceSubcomponents
.Where(tds => tds.TemplateID == templateID)
.Take(countToRemove)
.ToList();
foreach (var item in subcomponents)
{
TaskDeviceSubcomponents.Remove(item);
}
}
Note that it is important to use ToList
here so you are not iterating TaskDeviceSubcomponents
while removing some of its items. This is because LINQ uses lazy evaluation, so it doesn't iterate over TaskDeviceSubcomponents
until you iterate over subcomponents
.
Edit: I neglected to only remove the number of items contained in countToRemove
, so I added a Take
call after the Where
.
Edit 2: Specification for the Take()-Method: http://msdn.microsoft.com/en-us/library/bb503062(v=vs.110).aspx
Upvotes: 3