During my time working, I find that developers can get lazy and start using the COPY and PASTE commands to a degree that can make code unmanageable.
There are many things we can do to reduce, if not eliminate, the code management nightmare, however, the one way I will focus on is using extension methods.
So what are extension methods ? and why should we use extension methods ? Let’s try to answer these questions in a scenario.
Let us assume we have a type, and this type is called “Int”, in our application we use our Int types A LOT.
We find that we either keep re-coding certain snippets of code or just lazily applying the copy, paste and replace procedure in order to complete or patch our application.
Now what happens when that logic has a bug or needs to be changed ? would you go to each implementation and fix it ? wouldn’t life be easier if this piece of logic could be changed in just one place ?
I’m not saying the using extension methods is the ONLY approach, but it is the approach we will be going through.
Here are a few rules before we go on to the code:
- your extension classes should be public and static
- your extension methods should be public and static
Let’s assume we had an array of integers:
int[] numbers = new int[] { 1, 3, 5, 6, 8, 9, 10 };
We needed to loop through this list of integers and determine if each number is even or odd, additionally we needed to determine if each number is a prime number or not.
Lets attempt to code this without using extension methods (the not so manageable approach).
int[] numbers = new int[] { 1, 3, 5, 6, 8, 9, 10 }; foreach(int i in numbers) { Console.WriteLine(i.ToString()); bool isEven = ((i % 2) == 0); if(isEven) { Console.WriteLine("\tEven"); } else { Console.WriteLine("\tOdd"); } if(i == 1) { Console.WriteLine("\tNot Prime"); } else if (i == 2) { Console.WriteLine("\tIs Prime"); } else { bool isPrime = true; double boundry = Math.Floor(Math.Sqrt(i)); for (int j = 2; j <= boundry; ++j) { if ((i % j) == 0) { Console.WriteLine("\tNot Prime"); isPrime = false; break; } } if(isPrime) { Console.WriteLine("\tIs Prime"); } } }
notice how long and messy this code looks ? using extension methods we can make this code more elegant and managable.
lets start of by creating a new class file and we can call this “SimpleExtenionMethods.cs”
this class should contain the following:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ExtensionMethodSample { public static class SimpleExtensionMethods { public static bool IsEven(this int i) { return ((i % 2) == 0); } public static bool IsPrimeNumber(this int i) { if (i == 1) return false; if (i == 2) return true; double boundry = Math.Floor(Math.Sqrt(i)); for(int j = 2; j <= boundry; ++j) { if ((i % j) == 0) return false; } return true; } } }
and here’s the implementation
// number array int[] numbers = new int[] { 1, 3, 5, 6, 8, 9, 10 }; // out each result foreach(int i in numbers) { Console.Write("Testing #" + i.ToString() + ":\t"); if(i.IsEven()) { Console.Write("Evem"); } else { Console.Write("Odd"); } if(i.IsPrimeNumber()) { Console.Write( ", Prime Number"); } Console.WriteLine(); }
is that not so much simpler, elegent and far more readable ?
here’s the result:
Testing #1: Odd Testing #3: Odd, Prime Number Testing #5: Odd, Prime Number Testing #6: Even Testing #8: Even Testing #9: Odd Testing #10: Even
lets take this step further, what if we wanted to split the ODD and EVEN numbers into seperate list objects ?
lets create a new class file called “SlightlyComplexExtensions.cs”
the code should be as follows:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ExtensionMethodSample { public static class SlightlyComplexExtensions { public static Dictionary<string, List<int>> SplitNumbersIntoSections(this int[] iArr) { Dictionary<string, List<int>> result = new Dictionary<string, List<int>>(); result.Add("Odd", new List<int>()); result.Add("Even", new List<int>()); foreach(int i in iArr) { if(i.IsEven()) { result["Even"].Add(i); } else { result["Odd"].Add(i); } } return result; } } }
and here’s the implementation:
// number array int[] numbers = new int[] { 1, 3, 5, 6, 8, 9, 10 }; // split array into sections Dictionary<string, List<int>> numberSplit = numbers.SplitNumbersIntoSections(); // out each section foreach(string key in numberSplit.Keys) { // key will either be EVEN or ODD Console.WriteLine(key + ":"); // out the numbers in the section foreach(int i in numberSplit[key]) { Console.WriteLine("\t" + i.ToString()); } }
here’s the result:
Odd: 1 3 5 9 Even: 6 8 10
Let us now take this one more step further, we now wish to generate a third list containing the prime numbers, this can be done without changing the implementation code. All that changes is the extension method.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ExtensionMethodSample { public static class SlightlyComplexExtensions { public static Dictionary<string, List<int>> SplitNumbersIntoSections(this int[] iArr) { Dictionary<string, List<int>> result = new Dictionary<string, List<int>>(); result.Add("Odd", new List<int>()); result.Add("Even", new List<int>()); result.Add("Prime", new List<int>()); foreach(int i in iArr) { if(i.IsEven()) { result["Even"].Add(i); } else { result["Odd"].Add(i); } if(i.IsPrimeNumber()) { result["Prime"].Add(i); } } return result; } } }
here’s the result:
Odd: 1 3 5 9 Even: 6 8 10 Prime: 3 5