Click here to Skip to main content
Click here to Skip to main content
Go to top

Generic List (C#)

, 12 Aug 2009
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael T. Shrove
Software Developer U.S. Army / AMRDEC
United States United States
B.S. in Computer/Electrical Engineer from the University of Alabama Huntsville.
M.S.S.E in Software Engineering with Embedded Systems

Comments and Discussions

 
GeneralpropertyEditor for the propertyGrid Pinmembercolberg31-Mar-10 7:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140905.1 | Last Updated 12 Aug 2009
Article Copyright 2009 by Michael T. Shrove
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid