Extension Method is an excellent feature in C# 3.0. It is a mechanism by which new methods can be exposed from an existing type (interface or class) without directly adding the method to the type. Why do we need extension methods anyway ? Ok, that is the big story of lamba and LINQ. But from a conceptual standpoint, the extension methods establish a mechanism to extend the public interface of a type. The compiler is smart enough to make the method a part of the public interface of the type. Yeah, that is what it does, and the intellisense is very cool in making us believe that. It is cleaner and easier (for the library developers and for us programmers even) to add extra functionality (methods) not provided in the type. That is the intent. And we know that was exercised extravagantly in LINQ. The IEnumerable was extended with a whole lot set of methods to aid the LINQ design. Remember the Where, Select etc methods on IEnumerable. An example code snippet is worth a thousand words:-
static class StringExtensions { /// /// 'this' decorator signifies that this is an extension method. /// It must be appear only on a public static method. /// Such a method is added to the public interface of the type following /// the 'this' decorator. /// public static int ToInteger(this string s) { return Convert.ToInt32(s); } public static string Left(this string s, int position) { return s.Substring(0,position); } public static string Right(this string s, int position) { return s.Substring(s.Length - position); } }
You might be aware of all this hot news. But our topic of the day is neither Extension Methods nor LINQ. It is something that dates back to C++. And you will see at the end of this post that extension methods are a polished version of a C++ principle. Ok, let us try to read some code:-
int Add(SomeClass& sc, int x) { // Let us get to here a little later. } class SomeClass { private: int m_nNum; public: void SomeMethod(int n); public: int Num const { return this->m_nNum; } };
The code is simple - We have a class called SomeClass and a global function. The global function takes a SomeClass instance by reference and an integer by value. The intent of the function is to add x with m_nNum. But whether to save it to m_nNum or just return is a topic we will deal in a little while. But do we understand that the Add function and SomeClass are closely related ?
There are two principles to know in C++ to understand the relation.
Interface PrincipleFor a class X, all functions, including free functions, that both (a) "mention" X, and (b) are "supplied with" X are logically part of X, because they form part of the interface of X.
* Supplied with X means that the function is provided (distributed with) in the same header file as X.
So now, Add mentions SomeClass and (to keep the discussion short assume that it) is supplied with SomeClass. If that, then Add is a part of the public interface of X. That should convince you.
Koenig LookupWhen an unqualified name is used as the postfix-expression in a function call, other namespaces not considered during the usual unqualified lookup may be searched, and namespace-scope friend function declarations not otherwise visible may be found. These modifications to the search depend on the types of the arguments. Those are lines from the C++ standard and must be tough to understand like the verses in the Bible. So let us talk our language to understand that:
namespace CPP { class SomeClass { }; void Foo(SomeClass); } CPP::SomeClass sc; void main() { Foo(sc); }
Will you be still surprised that Foo(sc) call will link to the CPP::Foo ? Don't be. That is what the cryptic lines above talks about. Ok, one more example:
namespace CPP { class SomeClass { }; } void Foo(CPP::SomeClass); void main() { CPP::SomeClass sc; Foo(sc); // Got it ? }
So now down to my point, Extension Methods is a polished version of the Interface Principle (or Koenig Lookup) in C++. The facility has been in C++ for a long time but not sure if exercised well (and wisely). Had the intellisense been intelligent enough, C++ would claimed it a mighty feature. Since the C++ IDE has been the same sucking way for a long time now, C++ got the wrong outlook - a hard programming language.
Hey C#, No hard feelings. It is just a perspective. Either way, My compiler compiles your compiler.
Comments
Interesting view, and they are similar in the sense that both of them only affect how the compiler looks up a matching method. But in my opinion, the biggest advantage, and the reason for existence of extension methods is that you can call them with the object.method() syntax. Granted, it's syntactic sugar and the compiler simply translates that to the static method call, but it allows code to flow much more naturally.
Also, extension methods are the only way you can add methods to instantiated generic types - you could, for example, add a SumOfAll method to List only.
Templates and Generics are not fit for comparison. So besides your 'SumOfAll' statement, I guess the (V)C++ folks could have done a better job with the compiler. The C++ compiler even to this day seems to be a giant complex parser upgraded to C++ itself from BASIC or assembly language. While in the right means, it must have been much more powerful and super-intelligent providing a lot of something like 'Compiler Services'. Well a poor kid (C++) has to look up to a rich kid (C#).
Just want to say that I like your comment about "My compiler (C++) compiles your compiler (C#). Straight to the heart!