Background
You may already know how Extension Methods (one of the advance topics of C#) is defined. Some of you may be using it in your projects.
However, many of you may not be able to appreciate the scenarios in which the extension methods capability provides excellent leverage of code manageability and coordination among teams.
Practical project execution using Agile methology in real world has many challenges. That is further manifolded by the following scenarios,
- Teams are spread across geogrpahy, having different or almost opposite timezones.
- Teams are inducted progressively, where former teams are more experienced and knowledgeable on the domain and processes and later teams are still learning.
- Teams guided by different code reviewers
- Developers have extreme range of experience - from 12 months to 12 years, who have to churn out backlogs during sprints at high velocity.
Allow me to elaborate a scenario graphically. (
Do let me know with your comments if you have worked in projects of similar nature!)
Team A defined an Entity Class Department in a earlier sprint, which another Team B, need to extend in later sprint based on the feature they are working on.
Approach 1
Change the original class defined by Team A and add the properties.
Impact
The functions and API's that refer the earlier class, will need to undergo changes. This will increase the scope of work for Team B It will increase the effort for testing as regression test suites needs to run on all previous implementations.
The situation will complicate if there are external or dependent API's on this one as the changes must cascade there as well.
Approach 2
Do not touch the original class and add extension methods that is required by Team B to add their functionality.
Impact
Minimal, since the original class was not touched, all implementation related to it, will not get affected.
Thus, Extension Methods comes very handy in such situations.
Allow me to jump to the code part, straight. I will inherit from the former class and define my new class as follows. You may add the Save() method in this class or seperate based on your design pattern. It is included here for illustration purpose only.
- public class Person {
- public long PersonID {
- get;
- set;
- }
- public string FirstName {
- get;
- set;
- }
- public string LastName {
- get;
- set;
- }
- public DateTime DOB {
- get;
- set;
- }
- public string EntityCode {
- get;
- set;
- }
- }
-
- public class Department {
- public long DepmtID {
- get;
- set;
- }
- public string DepmtName {
- get;
- set;
- }
- public string DepmtSubject {
- get;
- set;
- }
- }
-
- public class ExtendedDepartment: Department {
-
- public ExtendedDepartment() {
- this.DepmtID = base.DepmtID;
- this.DepmtName = base.DepmtName;
- this.DepmtSubject = base.DepmtSubject;
- }
-
- public Person DepmtHead {
- get;
- set;
- }
- public void Save() {
- Console.WriteLine("Superindent successfully added to the Department.");
-
- }
- }
Now we will add the extension methods. Again, for additional illustration, I have added two new Extention methods to the Person class (though it is not required for the Department class to work)
Method 1
Creating the Full Name from the First Name and Last Name of the Person. This could be required for display to the user only and not required to be persisted.
Method 2
Find the Age of the Person given his DOB.
Method 3
Extension method to add the Department Head to the existing Department details. The Department Head is of type Person.
- public static class EntityExtensions
- {
- public static string FullName(this Person p)
- {
- return $"{p.FirstName} {p.LastName}";
- }
-
- public static int Age(this Person p)
- {
-
- var today = DateTime.Today;
-
- var age = today.Year - p.DOB.Year;
-
- if (p.DOB.Date > today.AddYears(-age)) age--;
- return age;
- }
-
- public static void AddDepartmentHead(this ExtendedDepartment d, Person h)
- {
- d.DepmtHead = h;
- }
- }
The extension method are included in the client method by importing the namespace only under which the Extension class is defined.
Thus, in the calling method, following is to be implemented.
- class Program
- {
- static void Main(string[] args)
- {
-
-
- DemoOfExtensions();
-
- Console.ReadLine();
- }
-
- static void DemoOfExtensions()
- {
-
- Person superitendent = new Person()
- {
- PersonID = 190987,
- FirstName = "Ram",
- LastName = "Kumar",
- DOB = Convert.ToDateTime("12-Apr-1980"),
- EntityCode = "T"
- };
-
-
-
- ExtendedDepartment d = new ExtendedDepartment()
- {
- DepmtID = 14,
- DepmtName = "Electrical and Electronics",
- DepmtSubject = "Electronics, Electrical, Advance Networking"
- };
-
-
- Console.WriteLine("Welcome to Professor " + superitendent.FullName() + " !");
- Console.WriteLine("He is currently " + superitendent.Age() + " yrs. old.");
-
-
- d.AddDepartmentHead(superitendent);
-
-
- Console.WriteLine("From base: "+ d.DepmtID + ", " + d.DepmtName + ", " + d.DepmtSubject);
-
-
- d.Save();
-
- }
- }
The output on the console is,
- Welcome to Professor Ram Kumar !
- He is currently 41 yrs. old.
- From base: 14, Electrical and Electronics, Electronics, Electrical, Advance Networking
- Superindent successfully added to the Department.
Conclusion
Use the Extension Methods when you do not want to touch the initial class and its related implementation. If that class is not sealed, you can use the above-mentioned approach very effectively.
Do share your feedback as always. Until then, stay safe and stay blessed.
Thank You !