Book Image

Instant .NET 4.5 Extension Methods How-to

By : Shawn Ricardo Mclean
Book Image

Instant .NET 4.5 Extension Methods How-to

By: Shawn Ricardo Mclean

Overview of this book

.NET extension methods is an essential feature to know and understand for all .NET developers. Usage of extension methods is found in applications ranging from small to large scale enterprise systems built using the .NET framework. Create and use extension methods the correct way to save your development time and maintainability costs. Instant .NET 4.5 Extension Methods How-to is a practical, hands-on guide that provides you with a number of clear, step-by-step exercises that will help you take advantage of the real power that is behind extension methods and gives you good knowledge of how to use them in your .NET applications. This book covers how to create, write, and use different types of extension methods. It will take you through a number of clear, practical recipes that will help you take advantage of the power of extension methods in the quickest possible way. You will also learn exactly how to create extension methods on strings, interfaces, classes such as IQueryable and IEnumerable, and so on. You will write them from scratch and then use them practically in your application. You will also learn the most suitable scenarios for using these extension methods.You will learn everything you need to know about creating your own extension methods and using them and other external extension methods.
Table of Contents (6 chapters)

Extension methods on enumerables (Should know)


Now, we move on to where extension methods are used the most, enumerated types. In an article by Eric Lippert, a principal developer on the C# team; LINQ was the reason extension methods were created in the first place. In this recipe, we will look at writing our own extension methods for the IEnumerable and IList type and take a look at an existing extension method in the .NET framework from the LINQ namespace.

Getting ready

Refer to the IEnumerableExtensions.cs and IListExtensions.cs file in the ExtensionMethods.Library project for the extension methods. These methods are used in the IEnumerableExtensionTests.cs file in the ExtensionMethods.Tests project.

How to do it...

The following code snippet shows the extension method Count() from the LINQ namespace:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    ICollection<TSource> is2 = source as ICollection<TSource>;
    if (is2 != null)
    {
        return is2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num++;
        }
    }
    return num;
}

The following code is our custom code snippet of an extension method for using bubble sort on an IList:

/// <summary>
/// Sort list using bubble sort algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
public static void BubbleSort<T>(this IList<T> list) where T : IComparable
{
    BubbleSort(list, 0, list.Count - 1);
}
/// <summary>
/// Sort list using bubble sort algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="startIndex">starting index</param>
/// <param name="endIndex">end index</param>
public static void BubbleSort<T>(this IList<T> list,
        int startIndex, int endIndex) where T : IComparable
{
    //Bubble Sort
    for (int i = startIndex; i < endIndex; i++)
        for (int j = endIndex; j > i; j--)
            if (list[j].IsLesserThan(list[j - 1]))
                list.Exchange(j, j - 1);
}
/// <summary>
/// Swap values of list by index
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="index1">1st index to swap with 2nd index</param>
/// <param name="index2">2nd index to swap with 1st index</param>
private static void Exchange<T>(this IList<T> list, int index1, int index2)
{
    T tmp = list[index1];
    list[index1] = list[index2];
    list[index2] = tmp;
}
private static bool IsLesserThan(this IComparable value, IComparable item)
{
    return value.CompareTo(item) < 0;
}

The following code snippet is our custom extension method for counting a sorted IEnumerable:

public static class IEnumerableExtensions
{
    public static int CountSorted<T>(this IEnumerable<T> values, T item) where T : IComparable
    {
        //convert to list to operate on it better.
        var list = values.ToList();

        //find random index of the item
        int index = list.BinarySearch(item);

        //if item isn't found, just return -1
        if (index < 0)
            return -1;


        int leftEdge = findLeftEdge(list, 0, index, item, Comparer<T>.Default);
        int rightEdge = findRightEdge(list, index, list.Count - 1, item, Comparer<T>.Default);

        //count it by taking away the left from the right
        return rightEdge - leftEdge + 1;
    }}

The following code snippets show how to implement these extension methods:

[TestMethod]
public void BubbleSortTest()
{
    IList<int> list = new List<int> { 3, 2, 1 };
    list.BubbleSort();
    Assert.IsTrue(new List<int>{1,2,3}.SequenceEqual(list));
}
[TestMethod]
public void BubbleSort_And_Count_Test()
{
    IList<int> list = new List<int> { 3,2,1,2 };
    int count = list.BubbleSort().CountSorted(2);
    Assert.AreEqual(2,count);
}

How it works...

The first code snippet of Count() was taken from the .NET framework System.Linq namespace using a decompile tool. The System.Linq namespace is filled with extension methods for enumerated types such as IEnumerable. This is an example that demonstrates that even the owners of classes can create extension methods for the sake of maintainability of the projects.

Our second code snippet is BubbleSort for the IList interface type. The algorithm operates on the instance object and sorts it using the bubble sort algorithm. This extension method has rules that govern what T should be, and should be inherited from the IComparable type or any type that can be compared, so that the algorithm can know which items are greater and smaller.

Our third code snippet CountSorted is used on sorted enumerable types using a modified binary search for an optimized count. This public method also calls private static functions which follows proper object-oriented guidelines.

There's more...

When working with enumerated types, there are a few key points to keep in mind:

  • Inheritance: In the BubbleSort_And_Count_Test method, we chained the CountSorted extension method (extending IEnumerable) on an IList type. This is possible as IList inherits from IEnumerable, whatever we can do on IEnumerable, we can also do on IList.

    int count = list.BubbleSort().CountSorted(2);
  • Manipulation: The BubbleSort extension method worked directly on the list it was operating on. As with classes, the list is passed by reference and can be manipulated. In the BubbleSortTest method, there was no need to assign it back to itself after calling the method.

    IList<int> list = new List<int> { 3, 2, 1 };
       list.BubbleSort(); //list is now sorted as {1,2,3}
  • Private extensions: In the IEnumerableExtensions class, we utilized both public and private extension methods so our class file can be properly structured. Both work just the same with the difference of public and private access.

    private static void Exchange<T>(this IList<T> list, int index1, int index2)

You will find that most of the extension methods you write will be operating on enumerated types.