Adding IndexOf to Linq

Posted in software by Christopher R. Wirz on Thu Mar 15 2012



LINQ stands for Language Integrated Query, which is one of the trend-setting features of C# .Net. It first appeared in .Net Framework 3.5 (February 2007) and can be applied to all sources of information. In other words, LINQ has been designed to handle collections of objects and values - the interface being IEnumerable. Despite these positive premises, LINQ seems to be missing one of the more familiar methods available in other languages: IndexOf(). While the LINQ/.Net way would be to use predicates, many algorithm definitions specify IndexOf, so implementing these algorithms in C# .Net is easier if that method is available.

Note: Not all enumerables are ordered (example: a Dictionary or a HashSet). In fact, an IEnumerable is not defined an ordered set, though most collections implementing IEnumerable happen to be ordered.

In order to create this functionality, extension methods can be created in the System.Linq namespace.


using System.Collections.Generic;

namespace System.Linq
{
    public static partial class Extensions
    {
        /// <summary>
        ///     Finds the index of the first item matching the predicate (-1 if no match)
        /// </summary>
        /// <typeparam name="T">The item type</typeparam>
        /// <param name="items">The item collection</param>
        /// <param name="predicate">a predicate such as i => f(i)==true</param>
        /// <returns>A 0-index value representing the position of the item first matching the predicate
        /// (-1 if no match)
        ///  </returns>
        public static int FirstIndexOf<T>(this IEnumerable<T> items, Func<T, bool> predicate)
        {
            if (items == null) { return -1;}
            if (predicate == null) { return -1;}

            int index = 0;
            foreach (var item in items)
            {
                if (predicate(item)) { return index;}
                index++;
            }
            return -1;
        }

        /// <summary>
        ///     Finds the index of an item within a collection
        /// </summary>
        /// <remarks>
        ///     Assume the items does not contain duplicate entries
		///		In other words, this functions more like FirstIndexOf if the collection allows duplicates.
        /// </remarks>
        /// <typeparam name="T">The item type</typeparam>
        /// <param name="items">The item collection</param>
        /// <param name="item">The item to find</param>
        /// <returns>A 0-index value representing the position of the item (-1 if no match)</returns>
        public static int IndexOf<T>(this IEnumerable<T> items, T item)
        {
            return items.FirstIndexOf(i => EqualityComparer<T>.Default.Equals(item, i));
        }
    }
}