Monday, July 14, 2008

A generic ListCollection class. Take 2.

I blogged recently about using public Collection instead of public List. The Visual Studio Code Analysis Team explained in their blog how to re-use List methods in classes derived from Collection<T> generic class. As you can see, their approach requires your class constructor to call base constructor of List<T>. To make developer's life easier, I proposed to make a generic ListCollection<T> class with such a constructor and inherit custom collection classes from it.
Then I read The Missing .NET #2: Collection<T> AddRange() article by Jason Kemp. He implemented "missing" methods of Collection<T> as extension methods. I added the same methods to my ListCollection<T> class. Because a default constructor of ListCollection<T> class guarantees that its protected Items property actually contains a List<T>, it is easier to implement "missing" methods; you just call corresponding methods of List<T>:

  /// <summary>
  /// A generic Collection class which ensures that it actually contains generic List.
  /// This provides us with an ability to re-use any public method of List&lt;T&gt; with a simple shell function.
  /// Such a shell could be implemented in a concrete implementation of this generic class,
  /// as extensions methods for ListCollection&lt;T&gt; or directly in ListColection&lt;T&gt; as it is done below.
  /// See "The Missing .NET #2: Collection&lt;T&gt; AddRange()"
  /// <see cref=""/> as well.
  /// </summary>
  public class ListCollection<T> : Collection<T>
    where T : class {
    public ListCollection()
      : base(new List<T>()) {
    public void AddRange(IEnumerable<T> values) {
    public bool Exists(Predicate<T> match) {
      return ((List<T>)this.Items).Exists(match);
    public T Find(Predicate<T> match) {
      return ((List<T>)Items).Find(match);
    public ListCollection<T> FindAll(Predicate<T> match) {
      ListCollection<T> items = new ListCollection<T>();
      //foreach (var item in ((List<T>)Items).FindAll(match)) {  //You can use this as an alternative to the above line
      //  items.Add(item);
      return items;
    public int FindIndex(Predicate<T> match) {
      return ((List<T>)Items).FindIndex(match);
    public int FindIndex(int startIndex, Predicate<T> match) {
      return ((List<T>)Items).FindIndex(startIndex, match);
    public int FindIndex(int startIndex, int count, Predicate<T> match) {
      return ((List<T>)Items).FindIndex(startIndex, count, match);
    public T FindLast(Predicate<T> match) {
      return ((List<T>)Items).FindLast(match);
    public int FindLastIndex(Predicate<T> match) {
      return ((List<T>)Items).FindLastIndex(match);
    public int FindLastIndex(int startIndex, Predicate<T> match) {
      return ((List<T>)Items).FindLastIndex(startIndex, match);
    public int FindLastIndex(int startIndex, int count, Predicate<T> match) {
      return ((List<T>)Items).FindLastIndex(startIndex, count, match);
    public void ForEach(Action<T> action) {
    public int RemoveAll(Predicate<T> match) {
      return ((List<T>)Items).RemoveAll(match);
    public bool TrueForAll(Predicate<T> match) {
      return ((List<T>)Items).TrueForAll(match);

An update: I added a "conversion" constructor Collection<T>(IList) to my ListCollection<T> generic class. It is useful and even made one method of this class itself simpler:

    // A default constructor
    public ListCollection() : base(new List<T>()) { }
    // A "converter" constructor, which does not copy the list passed in.
    // See
    public ListCollection(IList<T> list) : base(list) { }

    public ListCollection<T> FindAll(Predicate<T> match) {
      return new ListCollection<T>(((List<T>)Items).FindAll(match));