4

Hi I want to create my custom collection, I am deriving my custom collection class from CollectionBase class as below:

public class MyCollection : System.Collections.CollectionBase
{
    MyCollection(){}
    public void Add(MyClass item)
    {
        this.List.Add(item);
    }
}

class MyClass
{
    public string name;
}

Let me ask a few questions:

  1. Whether this approach is correct and new, as I working on .NET 3.5 framework.
  2. I want to expose this collection from my web service ( WCF) .How can I do that?
  3. Do I have to implement GetEnumerator?
  4. Whether this will Bind to DataGridView.
Artur INTECH
  • 6,024
  • 2
  • 37
  • 34
Ashish Ashu
  • 14,169
  • 37
  • 86
  • 117

5 Answers5

7

Deriving from List<T> is somewhat pointless, especially now that it has the IEnumerable<T> constructor and the availability of extension methods. It has no virtual methods that you can override except Equals, GetHashCode, and ToString. (I suppose you could derive from List<T> if your goal was to implement Java's toString() functionality for lists.)

If you want to create your own strongly-typed collection class and possibly customize the collection behavior when items are add/removed, you want to derive from the new (to .NET 2.0) type System.Collections.ObjectModel.Collection<T>, which has protected virtual methods including InsertItem and RemoveItem that you can override to perform actions at those times. Be sure to read the documentation - this is a very easy class to derive from but you have to realize the difference between the public/non-virtual and protected/virtual methods. :)

public class MyCollection : Collection<int>
{
    public MyCollection()
    {
    }

    public MyCollection(IList<int> list)
        : base(list)
    {
    }

    protected override void ClearItems()
    {
        // TODO: validate here if necessary
        bool canClearItems = ...;
        if (!canClearItems)
            throw new InvalidOperationException("The collection cannot be cleared while _____.");

        base.ClearItems();
    }

    protected override void RemoveItem(int index)
    {
        // TODO: validate here if necessary
        bool canRemoveItem = ...;
        if (!canRemoveItem)
            throw new InvalidOperationException("The item cannot be removed while _____.");

        base.RemoveItem(index);
    }
}
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • The hyperlink is right there in the text, but I'll add a code sample too. – Sam Harwell Jul 28 '09 at 05:46
  • As long as your objects are defined explicitly as the deriving class, eg, `MyCollection collection = new MyCollection();`, you don't need the methods to be virtual. You only need it if you have `List collection = new MyCollection();`, and that makes little sense in this case. I'm using inheritance here to get functionality, not to expand a class. Still, good point about the `Collection` class. Thanks. – Kobi Jul 28 '09 at 05:47
  • 1
    @Kobi: Using hide-by-name on non-virtual methods is a guaranteed way to cause a maintenance nightmare. As soon as someone operates on it as an `ICollection` instead of `MyCollection`, it's broken. If a method is non-virtual, assume that any attempt to override it will go horribly wrong. – Sam Harwell Jul 28 '09 at 05:52
  • Good point. I'll remember that one. You get +1 for the explanation. Thanks. – Kobi Jul 28 '09 at 06:03
  • Thanks for the explanation. Can you please give me what is advantange or disadvantage i get when deriving my collection from List??? – Ashish Ashu Jul 28 '09 at 07:17
  • @Ashish: What? That's the sole content of my answer...? – Sam Harwell Jul 28 '09 at 08:12
  • Note that Collection doesn't support sorting, but the Sort() method can be implemented with a few lines of code: http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/977ac532-afc9-46b7-bd73-a5cc41086b9c/ – salle55 Jan 25 '10 at 16:53
4

I think you would be better off using one of the container classes defined in System.Collections.Generic

  1. Whether this approach is correct and new, as I working on .NET 3.5 framework.
    • No. Use List or something instead.
  2. I want to expose this collection from my web service ( WCF) .How can I do that?
    • pass. haven't used WCF.
  3. Do I have to implement GetEnumerator?
    • not if you use one of the standard System.Collections.Generic container classes. It's already done for you
  4. Whether this will Bind to DataGridView.
    • Any of the standard collections that support IEnumerable will bind to controls pretty well. You could look at using IBindingListView if you want sorting and filtering.
Hamish Smith
  • 8,153
  • 1
  • 34
  • 48
  • 1
    In my experience, as long as the object is serializable, you probably won't encounter problems with WCF. Extending List is a good, as long as the contents are serializable too. Just note: Some other collections like Dictionary aren't serializable - but it's still possible to implement your own serializable "Dictionary" using a List. – Loki Jul 28 '09 at 06:58
3

If you want your own collection class you can also inherit from a generic collection to a non-generic class, eg:

public class MyCollection : List<MyClass>
{

}

This way you get all the functionality of a list (for example). You just need to add a few constructors.

Kobi
  • 135,331
  • 41
  • 252
  • 292
1

Why not using a generic collection?

using System;
using System.Collections.Generic;

namespace Test {
    class MyClass { 
    }
    class Program {
        static void Main(string[] args) {
            // this is a specialized collection
            List<MyClass> list = new List<MyClass>();
            // add elements of type 'MyClass'
            list.Add(new MyClass());
            // iterate
            foreach (MyClass m in list) { 
            }
        }
    }
}

EDIT: Ashu, if you want to do some validation on Add and Remove operations you could use a generic collection as member of your specialized collection:

using System;
using System.Collections.Generic;
namespace Test {
    class MyClass { 
    }
    class MyClassList {
        protected List<MyClass> _list = new List<MyClass>();
        public void Add(MyClass m) { 
            // your validation here...
            _list.Add(m);
        }
        public void Remove(MyClass m) {
            // your validation here...
            _list.Remove(m);
        }
        public IEnumerator<MyClass> GetEnumerator() {
            return _list.GetEnumerator();
        }
    }
    class Program {
        static void Main(string[] args) {
            MyClassList l = new MyClassList();
            l.Add(new MyClass());
            // iterate
            foreach (MyClass m in l) { 
            }
        }
    }
}
Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193
  • Since I want to validate the add remove and delete operation of the collection. This will give me more control if i create my own collection. – Ashish Ashu Jul 28 '09 at 05:24
0

Maybe I'm missing something here, but if you just need to add validations why don't you inherit from a generic collection and override the New() Remove() or any other method.

class CustomeCollection<T> : List<T>
{
    public new void Add(T item)
    {
        //Validate Here
        base.Add(item);
    }

    public new void Remove(T item)
    {
        //Validate Here
        base.Remove(item);
    }

}
kay.one
  • 7,622
  • 6
  • 55
  • 74
  • Thanks for the explanation. Can you please give me what is advantange or disadvantage i get when deriving my collection from System.Collections.ObjectModel.Collection??? – Ashish Ashu Jul 28 '09 at 07:17