Extension methods are one of the coolest features of C#. It allows our custom methods to be used on the objects without needing to extend or change the underlying class.
Extension methods are nothing but static methods. You can call them directly like any other static methods.
public sealed class User {
public int Id {set;get;}
public string Name {set;get;}
public int Age {set;get;}
public StatusCode Status {set;get;}
}
Let's add an extension method for this class that checks if this user is active or not.
public static class UserExtensions{
public static bool IsActive(this User user){
return user.Status == User.StatusCode.Active;
}
}
...
userObj.IsActive();
...
You may be thinking what's the big deal, we could add this method in the
User
class itself. However, we may not always have control over a class. It may be coming from a third party library and we may not be able to extend the class to add this method (because sealed
). That's where extension methods shine! It's only a static method and it can only access the public interface of the object. However, it makes it look like the object has the method and it allows us to write code in a declarative fashion.Extension methods are only static methods. Only difference from the static method is
this
keyword. You can also call it like a regular static method and it will work the same way: UserExtensions.IsActive(userObj)
Our famous
Linq
library is nothing but a collection of extension methods. Probably most of us have done the following a lot. var list = userList
.Where(i=>i.Status == User.StatusCode.Active);
We can create our toolbox by adding our own extension methods hence we can improve the code by using our new extension method.
var list = userList
.Where(i=>i.IsActive());
We can take this one step further by adding another extension method.
public static IEnumerable<User> OnlyActive(this IEnumerable<User> list) {
return list.Where(i=> i.IsActive());
}
Now our code reduced to this:
userList
.OnlyActive();
We can add other methods too.
public static IEnumerable<User> OlderThan(this IEnumerable<User> list, int age) {
return list.Where(i=> i.Age > age);
}
public static IEnumerable<User> YoungerThan(this IEnumerable<User> list, int age) {
return list.Where(i=> i.Age < age);
}
public static User GetById(this IEnumerable<User> list, int Id) {
return list.SingleOrDefault(i=> i.Id == Id);
}
so we can write as the following. Code is self explanatory...
userList
.OnlyActive()
.YoungerThan(20);
We can also add more generic methods.
public static class OtherExtensions{
public static bool IsNull(this object obj){
return obj == null;
}
public static bool IsNotNull(this object obj){
return !obj.IsNull();
}
public static void IfNotNull<T>(this T obj, Action<T> action){
if(obj.IsNotNull()){
action(obj);
}
}
}
It's also possible to use generics as in the last method
IfNotNull
. It expects an object of type T
, and if it is not null
, it calls the delegate function that's passed in. var exists = userList
.GetById(30)
.IsNotNull();
userList
.GetById(3)
.IfNotNull(user=> Console.WriteLine( user.Name + " found!"));
Extension methods are a great way to abstract logic. Its declarative nature makes the code base cleaner and more readable.