Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I found the "Extension method" concept of C# just wonderful. It enables us to do things like:

And The coolest thing about it IMHO is that adding a method doesn't break backward compatibility.

However, I found almost no extension methods in the .NET BCL. And it's very common that, I see a static method and extension methods come in mind.

When the BCL was designed, extension methods were not there. But why are they not converted to extension methods now? Specially when it does break backward compatibility? Any reasons?

share|improve this question
    
I would like to write a.Round() instead of Math.Round(a) and a.Pow(b) instead of Math.Pow(a,b). But Math.Max(a,b) is ok. –  Gulshan May 19 '11 at 11:31

2 Answers 2

The point of extension methods is to allow you to add features to classes you cannot modify or inherit from. For example, if in a very specific case you want to display an integer as a money,

  • either you create a static class HelloWorld with the method public static string DisplayIntAsMoney(int amount) and use it like HelloWorld.DisplayIntAsMoney(5990) to obtain "$US 59.90",
  • or you create an extension method and use it like 5990.AsMoney().

The first one is ugly. The second one is ugly too, but much shorter.

But extension methods don't have to be used everywhere to do everything. This is a tool. Don't use it abusively.

For example, if you've written a library with a class and you want to add features to it to use in another project, you have two choices:

  • Use an extension method,

  • Return to the former library and modify it by providing an inherited class which provides the feature or by adding the feature directly to the class.

The first one is ugly. Very ugly. It also forces you to violate the DRY principle, since you'll probably rewrite the same extension method again and again in many projects which will use the same library. The second one on the other hand let you provide more features without breaking backward compatibility (at least in the case you create an inherited class).


This being said, extension methods are pretty useful in two cases:

  • When you need to extend classes you cannot modify,

  • When you need to provide common features without having to modify the existing huge codebase or you have to provide features that may be turned on and off by adding or removing references to your project.

The first reason doesn't apply to .NET BCL. Microsoft has the source code. Microsoft can modify it directly, instead of using extension methods. It's exactly what happens actually.

The second reason applies to .NET codebase. But, wait, aren't they doing exactly this thing with LINQ, Reactive Extensions, etc.?


Edit following your comment:

There are four reasons why we have Math.Round(a) instead of a.Round():

  • Math.Round existed before extension methods appeared, and it's never a good idea to rewrite an existing API just for the sake of rewriting, breaking all legacy source code.

  • Having extension methods for Round or Pow but static methods for Max is just too confusing, especially when you don't use the API too often. Actually, I know that if I want something mathematical, I have to type Ma, autocomplete, and start to type the name of the method. With your approach, I would sometimes mistake by starting to type Ma, searching for the method, discovering that the method does not exist, recalling that it might be an extension method, removing Math. then starting to type in a way to obtain autocompletion for the extension method.

  • Math methods belong to System namespace. This namespace is declared in nearly every file of every project. This would mean that you'll have Round, Floor etc. autocompletion every time you enter an integer followed by a dot. It's just too annoying. Having too many methods in intellisense not only makes it difficult to find the good one, but it also decreases performance on slow computers.

  • float, double and int do not inherit from the same type. If LINQ extension methods are commonly associated with IEnumerable or some base types, it is impossible to do it with Math methods. The only way is to write code for every type, which is probably not the most elegant approach. With static methods, there are also overloads, but they are much shorter to write and easier to understand.

share|improve this answer
    
I was surprised to discover that the .Net string class is sealed. One of my very first java lessons involved inheriting from string and adding some useless functions. When I needed to do this in .Net I ended up using extension methods. But I can't help but wonder if inheritance wouldn't have been a better solution. What if I wanted to create several different permutations of the string class used for different situations? If that were the problem would I have ended up having been flooded by extensions methods that do no not apply for a particular situation? –  Tjaart May 19 '11 at 8:14
    
@Tjaart: That's why you have the concept of namespaces. You just implement every permutation you would have into a different namespace (and potentially in a different library), and then only include the namespace (library) you need for your specific situation. –  fretje May 19 '11 at 8:21
    
I guess this could work, but wouldn't this be misusing namespaces? I always thought of namespaces as broader categories. –  Tjaart May 19 '11 at 9:04
    
@Tjaart Java's String has been final since at the very least 1.0.2 (see aquaphoenix.com/ref/jdk1.0.2_api/java.lang.String.html), so how did you derive from String? Or were you using an alternative JDK? –  yatima2975 May 19 '11 at 10:20
    
I actually think it was an alternative JDK. My bad. –  Tjaart May 19 '11 at 10:24

My guess is that the CLR team has bigger fish to fry then go back and redo old designings. Unfortunately once something gets into the .Net framework it's there for good. If they could turn back time I bet there's a bunch of stuff they'd do different including the use of out/ref parameters, the use of certain interfaces and burning a bunch of base classes (MarshalByRef anyone) :)

Adding extensions methods for everything would make the framework a bit more cluttered. As you say you can pretty easily add extension methods for stuff yourself, just reference the old static methods

share|improve this answer
    
I did not mean "everything". I'm sorry my wording was confusing. I tried to say- there are many places where extension methods would have been appropriate and will not break backward compatibility. –  Gulshan May 19 '11 at 11:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.