13

I'm refactoring my code to use IList instead of List. I used List.RemoveAll in a couple of places, and noticed that IList does not have this method at all. Is there any good reason for this?

4
  • 2
    Because the language designers agreed that not all types implementing IList<T> should have a RemoveAll(Predicate<T>) method. Commented Aug 9, 2015 at 10:28
  • because I = Interface, contain abstract methods you have to implement, see this msdn.microsoft.com/en-us/library/… Commented Aug 9, 2015 at 10:28
  • 2
    I don't know the reason behind this interface design decision (probably trying to minimze the size of their interfaces?), but you can always write an extension method that covers you for any IList<>. Commented Aug 9, 2015 at 10:29
  • @AsfK: Could you write more concretely what that has to do with the question, please? Commented Aug 9, 2015 at 10:41

2 Answers 2

10

There is a principle in software engineering called interface segregation. It boils down to the notion that smaller interfaces are better than larger ones. When this idea is taken to the extreme, the ideal interface declares only one member - but let's not bother with that. The point is that interfaces should describe strict requirements, not convenience features.

In our specific case, the IList<T> interface declares the members that a type is required implement in order to be an IList<T>. Obviously, a type isn't required to implement RemoveAll in order to be an IList. It is convenient for a type to do so, but it's not required.

This is a valid use case for extension methods, though. You can define your own RemoveAll extension method for any IList<T> and keep the convenience.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! I understand the design principles. My question was more about this specific case - what can be a reason for System.Collections.Generic designers not to include RemoveAll in IList interface?
@SergeyKandaurov I would guess because they applied the above design principles for this specific case and figured that it's not a requirement they want to impose on people who implement these collections or a contract they want to maintain with the consumers of these collections. Keep in mind that RemoveAll can be implemented in terms of the already exposed members (without knowing its internals), so there's no reason to require the collection to implement it for you.
Makes sense now. Then I guess there should be some interface declaring RemoveAll for developer's convenience in order not to force using List<> or creating custom extension methods.
0

Although a general software design reason was explained by Theodoros Chatzigiannakis you might be interested in a solution when you do need a RemoveAll (maybe you received an IList from a library and want to manipulate that in an easier way). There is an answer here that might interest readers: https://github.com/dotnet/core/issues/2199

Based on the answers from the Dotnet core team, I understand that the main reason is legacy, but as they said, you can easily write an extension method. An example of such an extension method (source: https://www.extensionmethod.net/csharp/icollection-t/removeall)

using System;
using System.Collections.Generic;
using System.Linq;

public static class CollectionExtensions
{
    public static void RemoveAll<T>(this ICollection<T> @this, Func<T, bool> predicate)
    {
        List<T> list = @this as List<T>;

        if (list != null)
        {
            list.RemoveAll(new Predicate<T>(predicate));
        }
        else
        {
            List<T> itemsToDelete = @this
                .Where(predicate)
                .ToList();

            foreach (var item in itemsToDelete)
            {
                @this.Remove(item);
            }
        }
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.