Make Generic Extension Method step by step in CSharp

Mar 6, 2013 00:00 · 693 words · 4 minute read C# example

What is extension method?

“Extension methods enable you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type” (source). In other words by using extension method we embed our functionality in the class rather than make an instance of it and using it. LINQ is a set of extension methods that add various functionality to collection members such as IEnumerable.

Step by Step Example

Get All Names with IEnumerable

We can set collection of names into IEnumerable type and retrieve it when we need it.

Get all names

public IEnumerable<string> GetAllNames() {
	IEnumerable<string> enumerable=new string[]{"Amir","Jim","John","Tom","Jack"};
	return enumerable;
}

Get Names that start with J

If we want to get all names that retrieve with “J” we can create some filtering method and check the start character of each member .

Start with J

public static class Extentions {
	public static IEnumerable<string> StartWithJ(IEnumerable<string> NamesCollection) {
	    foreach (var name in NamesCollection) {
	        if (name.StartsWith("J")) {
	            yield return name;
	        }    
	    }
	}
}

Yield return” helps us to filter the values and put them in IEnumerable collection and return it when the iteration is finished.

In order to use it we can call this static class and method like below

Get names with J

public IEnumerable<string> GetNamesWithJ() {
	IEnumerable<string> allNames = GetAllNames();
	IEnumerable<string> startWithJ = Extentions.StartWithJ(allNames);
	return startWithJ;
}

Get Names start With “J” by Enumerable

It is also possible to embed the new method inside the IEnumerable class by adding “this” keyword to the input type. it will make it accessible for all the instances of IEnumerable that using this namespace.

Get Names start With

public static IEnumerable<string> EmbededStartWithJ(this IEnumerable<string> NamesCollection) {
	foreach (var name in NamesCollection) {
	    if (name.StartsWith("J")) {
	        yield return name;
	    }
	}
}

Get all names start with passed character

In order to make it more generic and allow the user to pass its desirable character into the method we can rarefaction the code as below.

Get all names start with passed character

public static IEnumerable<string> EmbededStartWith(this IEnumerable<string> NamesCollection,string character ) {
	foreach(var Name in NamesCollection) {
	    if(Name.StartsWith(character)) {
	        yield return Name;
	    }
	}
}

Make it generic for all types of variable

Our code is only valid for the string collections and it only looks up for the start character.

Therefore, we can not use it to get even numbers of “Integer” collection.

Get all numbers

public IEnumerable<int> GetAllNumbers() {
	IEnumerable<int> enumerable = new int[] { 1,2,3,4,5,6,7 };
	return enumerable;
}

As we are not fancy to create different methods for different input type we can make a generic filter.

generic extension

public static IEnumerable<T> EmbededFilter<T>(this IEnumerable<T> Collection, Filter<T> filter ) {
	foreach (var item in Collection) {
	    if (filter(item)) {
	        yield return item;
	    }
	}
}

delegate

 public delegate bool Filter<T>(T item);`

We allow our IEnumerable to accept all types of value and also passing our condition with a delegate that will be raised in each iteration of ours for each loop

Call it with named method

We can create a named method that checks our condition and then pass it to our delegate

calling with named method

public IEnumerable<int> GetEvenNumber() {
	IEnumerable<int> allNumbers = GetAllNumbers();
	IEnumerable<int> embededFilter = allNumbers.EmbededFilter(IsEvenNumber);
	return embededFilter;
}

named method

public bool IsEvenNumber(int input) {
	return input%2==0;
}

IsEvenNumber will be pass to our delegate and it raised every time it check the if condition.

Use Anonymous method

Instead of making new method and passing it to our delegate we can use an anonymous method and just call it inline.

allNumbers.EmbededFilter(delegate(int item) { return item%2 == 0; });

Call it with lambda expressions

We can simplify it even more and ended up with some lambda expression like below.

lambda expression

allNumbers.EmbededlambdaFilter(item => item % 2 == 0);

Also rather than calling the new delegate , use lambda Func embedded delegate.

embedded filter

public static IEnumerable<T> EmbededlambdaFilter<T>(this IEnumerable<T> Collection, Func<T,bool> filter) {
	foreach (var item in Collection) {
	    if (filter(item)) {
	        yield return item;
	    }
	}
}

This delegate accepts all the method with any input type which return a boolean value.

Download

Feel free to download the full source code of this example from my GitHub.