Make Generic Extension Method step by step in CSharp
Mar 6, 2013 00:00 · 693 words · 4 minute read
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 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.