65.9K
CodeProject is changing. Read more.
Home

Generic List (C#)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (19 votes)

Jul 27, 2009

CPOL

1 min read

viewsIcon

184030

downloadIcon

2876

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();