Interfaces are used to logically encapsulate definitions for a group of related functionalities, contains only the signatures of methods, properties, events or indexers. On the flip side — “extension methods enable you to ‘add’ methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.” I suppose you already know it. Now the question arises, even if this was somehow ‘technically possible’ … why do you need it ?
A famous man once said “with great power comes great responsibilities” – who said that what is that even mean, don’t matter. I said that because he said it. So now he was famous and getting said by two well known guys. urgh … let’s track this from the beginning…
Don’t extension methods simply hide the behavior that you just can’t see upfront when you’re looking at a class for the first time ? … They might. And that’s why I see them as a responsibility.
So what’s the deal ? Why in the infinite wisdom you want to stick these together ? Interfaces are strictly about declaration and extension methods ought to be implemented ! You might ask why not use abstract base classes ? Good question ! Please follow along…
- To answer the question above, sometimes we need a behavior that was also independent of any members’ implementation. From my experience, sometimes you don’t really need another class to implement your interface !
[ *** hint ! hint ! *** ] - Another way to put it is : Unlike C++, C# cannot take an unknown class type as base class, hence Extension Methods seems to be the right way. ( … with some unique benefits which C++ might not offer )
Enough talking … so for item # 1 above, let me give you an example rather :
I once had a project with multiple modules in it, each would’ve its own configurations. So I came up with following interface :
public interface IConfiguration { // Gets the configuration value by param name string GetConfig(string configName); // Gets the configuration value by param name // and default value is returned if value not found string GetConfig(string configName, string defaultVal); }
And I was done, each module would’ve dedicated class to implement these two functions however it wants. It worked as expected, until one day when I needed to read some config values from *.config files, operating system environment variables etc. These were still configurations, so I did not actually need new class or interface. Adding just a signature in the interface and again leaving it upto each module to implement might be perfectly legal – but wait a second !!!
- Did I needed to write same function again and again to read same kind of configurations ?
- Would maintaining, tracking or debugging that code be easier ? Of course not !
- What happened to DRY ?
I simply needed to extend IConfiguration interface to support it. There you go ! I needed to write it once and make it accessible to all implementations of IConfiguration, that’s it !
So I added an extension method in the same folder called “Common” where I had IConfiguration.cs :
public static class Extensions { // Some sample extension method ... public static string JoinStrings(this string input, string parameter) { return (input + parameter); } // returns system configuration, notice first parameter ! public static string GetSysConfig(this IConfiguration config, string param) { return "system parameter value"; } // returns system configuration with default value, notice first parameter ! public static string GetSysConfig(this IConfiguration config, string param, string default) { return "system parameter value or default" ?? defaultValue; } }
Cheers !