Extension methods have been available in C# for many years now. As with all language features they are open to abuse, but used well they can enable developers to produce fluent interfaces and stateless methods for reuse.
One of my bugbears is code that is hard to understand. Or more accurately code I have to think about in order to understand.
Take the Startup class in ASP .Net Core APIs. In the ConfigureServices() method there is often a lot of code adding services to the IServiceCollection to enable Dependency Injection. This code can be overwhelming when you first look at it. E.g.
services .AddScoped<IMyService, MyService>() .AddScoped<IMyService2, MyService2>() .AddScoped<IMyService3, MyService3>() ...
I like to organise code according to the functionality it supports. Many of these services support a specific area of functionality. A well-named extension method placed in the folder for a particular piece of functionality makes it easy to group configuring services it relies on together. The intention of the code in the ConfigureServices() method then becomes much easier to understand. E.g.
services .AddFeature1() .AddFeature2() .AddFeature3() ...
Another area I find extension methods useful is with dynamically building up queries using the Elasticsearch Nest client or the MongoDB Driver. Very often, I have to build a query based on an optional parameter in the request. This can lead to lots of if statements checking for the parameter. If the parameter is present the query is then extended. E.g.
var filter = Builders<MyCollection>.Filter.Empty; if (property1!= null) { filter &= Builders<MyCollection>.Filter.Eq(x => x.Property1, property1); } ...
Very quickly this code can become so long and unreadable that it’s hard to understand what the intention is. Moving this code into extension methods leads to code like this where the intention is much clearer.
var filter = Builders<MyCollection>.Filter .Empty .ByProperty1(property1) .ByProperty2(property2) ...;
The obvious benefit to all this is that it helps the next person who works on this to quickly understand what the code is trying to do. It’s easier to make changes and there are likely to be fewer bugs.