Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't C# static class extension methods supported?

I know from this question that extension methods can only operate on class instances, not the static class itself. This means I can't extend useful static classes like Convert and Math.

What I want to know is, why is this the case? From the link above, there are some suggestions on how the C# team could have implemented this kind of functionality. Is there some philosophical reason why it isn't supported?

For example, here's a rationale behind why there is no built-in LINQ ForEach<T> extension for IEnumerable<T>.

like image 324
Justin Morgan Avatar asked Feb 05 '11 19:02

Justin Morgan


People also ask

Why is C not outdated?

The C programming language doesn't seem to have an expiration date. It's closeness to the hardware, great portability and deterministic usage of resources makes it ideal for low level development for such things as operating system kernels and embedded software.

Why is C the fastest language?

But to answer your question, well-written C code will generally run faster than well-written code in other languages because part of writing C code "well" includes doing manual optimizations at a near-machine level.

Why is C faster than Java?

Java is an object-oriented, high level, and interpreted language. Java uses objects, while C uses functions. Java is easier to learn and use because it's high level, while C can do more and perform faster because it's closer to machine code.

Why is C difficult?

It is hard to learn because: It has complex syntax to support versatility. It is a permissive language—you can do everything that's technically possible, even if not logically right. It is best learned by someone who already has a foundation with C programming.


2 Answers

the C# team could have implemented this kind of functionality. Is there some philosophical reason why it isn't supported?

There's no technical reason, and no philosophical reason. However, as I often point out, I don't have to provide a justification for not doing a feature. Features aren't cheap; they are extremely expensive and they must not only justify their own cost, they must justify the opportunity cost of not doing the hundred other features we could have done with that budget. We must justify the cost of features to our stakeholders, but we need not justify saving time and effort by not implementing features that don't meet our bar.

In particular, the proposed feature does nothing for LINQ; extension methods were added to make LINQ work. Anything that didn't make LINQ work was very hard to get into C# 3.0; we had a lot of work on the schedule and not much time to do it in. (I was surprised that automatic properties made it in.) Cutting an unnecessary feature before even designing it saved a lot of time and effort that was spent on other things that do make LINQ work.

In short: the suggested feature has never met our bar for net benefit over cost, and we've always had more important features to spend our limited time and effort on.

like image 55
Eric Lippert Avatar answered Oct 17 '22 22:10

Eric Lippert


After reading through the answers, as well as some related questions, I've assembled my understanding of the issue here.

How extension methods work

First, it's important to realize that extensions are just syntactic sugar for static methods.

// Say you have an extension method that looks like this: class Extensions {     public static void Extend(this SomeClass foo) {} }  // Here's how you call it SomeClass myClass; myClass.Extend();  // The compiler converts it to this: Extensions.Extend(myClass); 

The method doesn't actually become part of the class. This is why you can't access private members from an extension method. Extension methods change C# syntax only, and do not violate the concept of OOP accessibility. In fact, if you write an extension method and a normal static method that do the same thing, then decompile the MSIL, they are exactly the same.

Why extension methods exist

So if they don't add actual functionality, why have extension methods at all? The answer is LINQ:

// LINQ makes this easy to read array.Where(i => i&1 == 0).Select(i => i*i);  // Without extension methods, we would have to do it like this Enumerable.Select(Enumerable.Where(array, i => i&1 == 0), i => i*i); 

In a way, all of LINQ is just syntactic sugar, since everything it can do could be written in a clunky, non LINQy way. Obviously the C# team felt that the readability gained by LINQ was worth it, but it begs the question, "why did they stop there?"

Why not other extension types?

Eric Lippert, one of the C# compiler devs, described in a blog post that a huge part of C# 3 was creating all of the constructs necessary for LINQ: "implicitly typed locals, anonymous types, lambda expressions, extension methods, object and collection initializers, query comprehensions, expression trees, [and] improved method type inference." Because the C# team was the most resource-limited team for the 2008 .NET release, additional types of extensions that weren't strictly necessary for LINQ were not included.

The team did consider implementing extension properties in C# 4, and actually wrote a working prototype, but it was dropped when they discovered it would not enable the WPF team as implemented (which was one of the motivators for the feature). Eric Lipper later said they they did consider extension methods for static classes, but could not justify the real-world benefits against the costs of implementation, testing, and maintenance.

A workaround

It is possible to write an extension method that gets close:

public static TResult DoSomething<TType, TResult>(this TType @class)     {         // access static methods with System.Reflection         return default(TResult);     }  // This works, but poorly typeof(Math).DoSomething(); typeof(Convert).DoSomething(); 

But it's pretty ugly. It requires reflection, and can't support any kind of intelligent typing, since any Type can call it and that's likely not the intended functionality.

like image 45
Justin Morgan Avatar answered Oct 17 '22 22:10

Justin Morgan