Extension methods for encapsulation and reusability
- by tzaman
In C++ programming, it's generally considered good practice to "prefer non-member non-friend functions" instead of instance methods. This has been recommended by Scott Meyers in this classic Dr. Dobbs article, and repeated by Herb Sutter and Andrei Alexandrescu in C++ Coding Standards (item 44); the general argument being that if a function can do its job solely by relying on the public interface exposed by the class, it actually increases encapsulation to have it be external. While this confuses the "packaging" of the class to some extent, the benefits are generally considered worth it.
Now, ever since I've started programming in C#, I've had a feeling that here is the ultimate expression of the concept that they're trying to achieve with "non-member, non-friend functions that are part of a class interface". C# adds two crucial components to the mix - the first being interfaces, and the second extension methods:
Interfaces allow a class to formally specify their public contract, the methods and properties that they're exposing to the world.
Any other class can choose to implement the same interface and fulfill that same contract.
Extension methods can be defined on an interface, providing any functionality that can be implemented via the interface to all implementers automatically.
And best of all, because of the "instance syntax" sugar and IDE support, they can be called the same way as any other instance method, eliminating the cognitive overhead!
So you get the encapsulation benefits of "non-member, non-friend" functions with the convenience of members. Seems like the best of both worlds to me; the .NET library itself providing a shining example in LINQ. However, everywhere I look I see people warning against extension method overuse; even the MSDN page itself states:
In general, we recommend that you implement extension methods sparingly and only when you have to.
So what's the verdict? Are extension methods the acme of encapsulation and code reuse, or am I just deluding myself?