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:
1 2 3 4 | 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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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