6

When it comes to extension methods class names seem to do nothing, but provide a grouping which is what name-spaces do. As soon as I include the namespace I get all the extension methods in the namespace. So my question comes down to this: Is there some value I can get from the extension methods being in the static class?

I realize it is a compiler requirement for them to be put into a static class, but it seems like from an organizational perspective it would be reasonable for it to be legal to allow extension methods to be defined in name-spaces without classes surrounding them. Rephrasing the above question another way: Is there any practical benefit or help in some scenario I get as a developer from having extension methods attached to the class vs. attached to the namespace?

I'm basically just looking to gain some intuition, confirmation, or insight - I suspect it's may be that it was easiest to implement extension methods that way and wasn't worth the time to allow extension methods to exist on their own in name-spaces.

Joshua Enfield
  • 17,642
  • 10
  • 51
  • 98
  • They *could* share static instance variables of the class, of course... Also, keep in mind you can still call extension methods through the regular class syntax. – James Michael Hare Apr 26 '12 at 20:25
  • 3
    C# is _all_ about classes. The development of the language and the whole CLR/.NET system came from the "we'd really rather not have things not in classes" school of programming inherited from java and the JVM. – Will Apr 26 '12 at 20:30
  • 1
    Let's turn the question on its head: how would a method be defined outside a type? –  Apr 26 '12 at 21:08
  • 1
    And the other way around: how would you call a method that isn't defined in a class? There are some cases when you want to call `Enumerable.ToList` explicitly. –  Apr 30 '12 at 08:52

4 Answers4

3

Perhaps you will find a satisfactory answer in Eric Lippert's blog post Why Doesn't C# Implement "Top Level" Methods? (in turn prompted by SO question Why C# is not allowing non-member functions like C++), whence (my emphasis):

I am asked "why doesn't C# implement feature X?" all the time. The answer is always the same: because no one ever designed, specified, implemented, tested, documented and shipped that feature. All six of those things are necessary to make a feature happen. All of them cost huge amounts of time, effort and money. Features are not cheap, and we try very hard to make sure that we are only shipping those features which give the best possible benefits to our users given our constrained time, effort and money budgets.

I understand that such a general answer probably does not address the specific question.

In this particular case, the clear user benefit was in the past not large enough to justify the complications to the language which would ensue. By restricting how different language entities nest inside each other we (1) restrict legal programs to be in a common, easily understood style, and (2) make it possible to define "identifier lookup" rules which are comprehensible, specifiable, implementable, testable and documentable.

By restricting method bodies to always be inside a struct or class, we make it easier to reason about the meaning of an unqualified identifier used in an invocation context; such a thing is always an invocable member of the current type (or a base type).

Community
  • 1
  • 1
AakashM
  • 62,551
  • 17
  • 151
  • 186
  • 2
    Note that in the last paragraph of that article I hint that we are considering the feature for a future version, and in fact, the Roslyn C# scripting / REPL scenarios do support "top level" methods and statements. – Eric Lippert Apr 30 '12 at 14:35
1

To me putting them in the class is all about grouping related functions inside a class. You may have a number of extension methods in the same namespace. If I wanted to write some extension methods for the DirectoryInfo and FileInfo classes I would create two classes in an IO namespace called DirectoryInfoExtensions and FileInfoExtensions.

You can still call the extension methods like you would any other static method. I dont know how the compiler works but perhaps the output assembly if compiled for .net 2 can still be used by legacy .net frameworks. It also means the existing reflection library can work and be used to run extension methods without any changes. Again I am no compiler expert but I think the "this" keyword in the context of an extension method is to allow for syntactical sugar that allows us to use the methods as though they belong to the object.

Bronumski
  • 14,009
  • 6
  • 49
  • 77
1

The .NET Framework requires that every method exist in a class which is within an assembly. A language could allow methods or fields to be declared without an explicitly-specified enclosing class, place all such methods in assembly Fnord into a class called Fnord_TopLevelDefault, and then search the Fnord_TopLevelDefault class of all assemblies when performing method lookup; the CLS specification would have to be extended for this feature to work smoothly for mixed-language projects, however. As with extension methods, such behavior could be CLS compliant if the CLS didn't acknowledge it, since code in a language which didn't use such a feature could use a "free-floating" method Foo in assembly Fnord by spelling it Fnord_TopLevelDefault.Foo, but that would be a bit ugly.

A more interesting question is the extent to which allowing an extension method Foo to be invoked from an arbitrary class without requiring a clearly visible reference to that class is less evil than would be allowing a non-extension static methods to be likewise invoked. I don't think Math.Sqrt(x) is really more readable than Sqrt; even if one didn't want to import Math everywhere, being able to do so at least locally could in some cases improve code legibility considerably.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

They can reference other static class members internally.

You should not only consider the consumer side aspect, but also the code maintenance aspect.

Even though intellisense doesn't distinguish with respect to the owner class, the information is still there through tool tips and whatever productivity tools you have added to your IDE. This can easily be used to provide some context for the method in what otherwise would be a flat (and sometimes very long) list.

Consumer wise, bottom line, I do not think it matters much.

Tormod
  • 4,551
  • 2
  • 28
  • 50