简体   繁体   中英

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> .

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.

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.

Extension methods operate on objects, not classes. If you want an extension method to operate on a class, I suppose you could do this:

public static T DoSomething<T>(this T @class) 
    where T:Type
{
    // access static methods via reflection...
    return @class;
}

I believe the answer for your question is because it doesn't make any sense to extend with static methods . Main reason behind introducing Extension methods is not extending class which you do not own. Main reason is that it will allow reduce methods nesting in examples like these:

 Enumerable.Select(Enumerable.Where(arr, i => i & 1 == 0), i => i*i); // not the best thing I ever read

 arr.Where(i => i&1 == 0).Select(i => i*i); // wow, I see! These are squares for odd numbers

That is why there is no such point to have extension methods for static classes.

Static extensions are possible in F# :

type Platform = 
    | Win32
    | X64
    override this.ToString() = 
        match FSharpValue.GetUnionFields(this, typeof<Platform>) with
        | case, _ -> case.Name.Replace('X', 'x')

type Environment with
    static member Platform =
        if System.IntPtr.Size = 8 then Platform.X64 else Platform.Win32

Well its not only about not implemented, but it will cause confusion of where the method belongs to? Static extensions were introduced because linq came in later version and only to support linq in easy to code way, static extensions are useful.

Static extensions are useful only to make code more readable. It has no significance at runtime or compile time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM