Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Generic List (C#)

0.00/5 (No votes)
12 Aug 2009 1  
Generic List based object that acts as a List but with built-in events

Introduction

This is a C# List based object that has the same functionality as a list but as the built-in events that should have been there from the start. It has the following events:

  • BeforeItemAdded
  • ItemAdded
  • BeforeItemRemoved
  • ItemRemoved
  • ItemsCleared

Background 

I created this GenericList because I kept finding myself needing events like ItemAdded or ItemRemoved everytime I used the list. So I created this generic list. 

The GenericList Inherits from the List Interface 

You can see that implemented from the IList interface. I took all the functions that the interface implements and wrapped it back to a List inside. 

public class GenericList<T> : IList<T>
{
    #region Members
    private List<t> m_pItems = null;
    #endregion

Examples of Wrapping

#region IList Methods
        // Summary:
        //     Gets or sets the element at the specified index.
        //
        // Parameters:
        //   index:
        //     The zero-based index of the element to get or set.
        //
        // Returns:
        //     The element at the specified index.
        //
        // Exceptions:
        //   System.ArgumentOutOfRangeException:
        //     index is not a valid index in the System.Collections.Generic.IList<t>.
        //
        //   System.NotSupportedException:
        //     The property is set and the System.Collections.Generic.IList<t> 
        //     is read-only.
        public T this[int index] 
        {
            get { return this.Items[index]; }
            set { this.Items[index] = value; }
        }
        // Summary:
        //     Determines the index of a specific item in the 
        //     System.Collections.Generic.IList<t>.
        //
        // Parameters:
        //   item:
        //     The object to locate in the System.Collections.Generic.IList<t>.
        //
        // Returns:
        //     The index of item if found in the list; otherwise, -1.
        public int IndexOf(T item)
        {
            return this.Items.IndexOf(item);
        }
        //
        // Summary:
        //     Inserts an item to the System.Collections.Generic.IList<t> 
        //     at the specified index.
        //
        // Parameters:
        //   index:
        //     The zero-based index at which item should be inserted.
        //
        //   item:
        //     The object to insert into the System.Collections.Generic.IList<t>.
        //
        // Exceptions:
        //   System.ArgumentOutOfRangeException:
        //     index is not a valid index in the System.Collections.Generic.IList<t>.
        //
        //   System.NotSupportedException:
        //     The System.Collections.Generic.IList<t> is read-only.
        public void Insert(int index, T item)
        {
            OnBeforeItemAdded(this, new GenericItemEventArgs<t>(item));
            this.Items.Insert(index, item);
            OnItemAdded(this, new GenericItemEventArgs<t>(item));
        }
        //
        // Summary:
        //     Removes the System.Collections.Generic.IList<t> 
        //     item at the specified index.
        //
        // Parameters:
        //   index:
        //     The zero-based index of the item to remove.
        //
        // Exceptions:
        //   System.ArgumentOutOfRangeException:
        //     index is not a valid index in the System.Collections.Generic.IList<t>.
        //
        //   System.NotSupportedException:
        //     The System.Collections.Generic.IList<t> is read-only.
        public void RemoveAt(int index)
        {
            OnBeforeItemRemoved(this, new GenericItemEventArgs<t>(this.Items[index]));
            this.Items.RemoveAt(index);
            OnItemRemoved(this, new EventArgs());
        }
        #endregion  

I also add the functions and properties of the ICollection interface, IEnumerable<t> interface, and the IEnumerable interface.

Events

The events I added are the ones I thought were most appropriate for the list.

#region Events
        /// <summary>
        /// Raises when an item is added to the list.
        /// </summary>
        public event EventHandler<GenericItemEventArgs<T>> ItemAdded;
        /// <summary>
        /// Raises before an item is added to the list.
        /// </summary>
        public event EventHandler<GenericItemEventArgs<T>> BeforeItemAdded;
        /// <summary>
        /// Raises when an item is removed from the list.
        /// </summary>
        public event EventHandler<EventArgs> ItemRemoved;
        /// <summary>
        /// Raises before an item is removed from the list.
        /// </summary>
        public event EventHandler<GenericItemEventArgs<T>> BeforeItemRemoved;
        /// <summary>
        /// Raises when the items are cleared from the list.
        /// </summary>
        public event EventHandler<EventArgs> ItemsCleared;
        #endregion

Event Methods

These are the functions that check whether the event is null or not.

#region Event Methods
        /// <summary>
        /// Raises when an Item is added to the list.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">GenericItemEventArgs</param>
        protected virtual void OnItemAdded(object sender, GenericItemEventArgs<T> e)
        {
            if (ItemAdded != null)
                ItemAdded(sender, e);
        }
        /// <summary>
        /// Raises before an Item is added to the list.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">GenericItemEventArgs</param>
        protected virtual void OnBeforeItemAdded
        	(object sender, GenericItemEventArgs<T> e)
        {
            if (BeforeItemAdded != null)
                BeforeItemAdded(sender, e);
        }
        /// <summary>
        /// Raises when an Item is removed from the list.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventsArgs</param>
        protected virtual void OnItemRemoved(object sender, EventArgs e)
        {
            if (ItemRemoved != null)
                ItemRemoved(sender, e);
        }
        /// <summary>
        /// Raises before an Item is removed from the list.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">GenericItemEventArgs</param>
        protected virtual void OnBeforeItemRemoved
        	(object sender, GenericItemEventArgs<T> e)
        {
            if (BeforeItemRemoved != null)
                BeforeItemRemoved(sender, e);
        }
        /// <summary>
        /// Raises when the Items are cleared from this list.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        protected virtual void OnItemsCleared(object sender, EventArgs e)
        {
            if (ItemsCleared != null)
                ItemsCleared(sender, e);
        }
        #endregion

Custom EventArgs

When creating the Events for the functions: Add, Remove, Insert, and RemoveAt I wanted a way for the developer to have access or knowledge of the item being removed or added on the events, so I created a custom EventArgs. I created the GenericItemEventArgs which supplies the developer to the item being added or removed for quick access. 

public class GenericItemEventArgs<T> : EventArgs
    {
        /// <summary>
        /// Item
        /// </summary>
        public T Item { get; private set; }
        /// <summary>
        /// Default constructor
        /// </summary>
        /// 
        public GenericItemEventArgs(T item)
        {
            this.Item = item;
        }
    }

Using the Code 

The list is pretty simple to use. It is identical to the C# List but with events. It has the same function names and everything. If you can use the C# list, you can use this list. 

Examples of code of how to use the list: 

GenericList<int> List = new GenericList<int>()
List.ItemAdded += 	new EventHandler<Tshrove.GenericList.GenericItemEventArgs<int>>
		(List_ItemAdded);
List.ItemRemoved += new EventHandler<EventArgs>(List_ItemRemoved);
List.ItemsCleared += new EventHandler<EventArgs>(List_ItemsCleared);
List.BeforeItemAdded += new EventHandler<Tshrove.GenericList.GenericItemEventArgs<int>>
			(List_BeforeItemAdded);
List.BeforeItemRemoved += new EventHandler
	<Tshrove.GenericList.GenericItemEventArgs<int>>(List_BeforeItemRemoved);
 // Adding and Removing Items from the list.
 List.Add(5);
 List.Remove(5);
 List.Add(10);
 List.Add(11);
 List.Clear(); 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here