为什么不支持C#静态类扩展方法?
我从这个问题中知道,扩展方法只能对类实例进行操作,而不能对静态类本身进行操作。 这意味着我不能扩展像Convert
和Math
这样有用的静态类。
我想知道的是,这是为什么呢? 从上面的链接中,有一些关于C#团队如何实现这种function的build议。 有没有支持的哲学理由?
例如,下面是为什么IEnumerable<T>
没有内置的LINQ ForEach<T>
扩展的基本原理 。
C#团队可能已经实现了这种function。 有没有支持的哲学理由?
没有技术上的理由,也没有哲学上的理由。 但是,正如我经常指出的那样,我不必提供不做function的理由。 function不便宜; 他们是非常昂贵的,他们不仅要certificate自己的成本是合理的,而且还必须certificate我们没有完成我们在这个预算中可能完成的其他function的机会成本。 我们必须向我们的利益相关者certificatefunction的成本,但是我们没有理由通过不实现不符合我们要求的function来节省时间和精力。
特别是,提议的function对LINQ没有任何作用; 添加了扩展方法使LINQ工作。 任何不能使LINQ工作的东西很难进入C#3.0; 我们在日程安排上做了很多工作,并没有太多的时间去做。(我惊讶于自动化的特性使它成为了现实。)在devise之前削减不必要的function,节省了大量花在其他上的时间和精力让LINQ工作的东西。
简而言之,build议的function从来没有达到我们的净效益和成本的标准,而且我们一直有更多的重要function来花费我们有限的时间和精力。
在阅读了答案以及相关的问题之后,我已经在这里汇总了我对这个问题的理解。
扩展方法如何工作
首先,认识到扩展只是静态方法的语法糖是很重要的。
// 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);
这个方法实际上并不属于这个类的一部分。 这就是为什么你不能通过扩展方法访问私有成员 。 扩展方法只改变C#语法,并不违反OOP可访问性的概念。 实际上,如果你写了一个扩展方法和一个正常的静态方法来做同样的事情,那么反编译MSIL就完全一样了 。
为什么存在扩展方法
所以如果他们不添加实际的function,为什么有扩展方法呢? 答案是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);
从某种意义上说,所有的LINQ都只是语法上的糖,因为它所能做的一切都可以用笨重的,非LINQ的方式来编写。 很明显,C#团队认为LINQ获得的可读性是值得的,但是它引出了一个问题:“他们为什么要在那里停下来?
为什么不用其他扩展types?
C#编译器开发人员之一Eric Lippert在博客文章中描述,C#3的一大部分是创buildLINQ所需的所有结构: “隐式types化的局部variables,匿名types,lambdaexpression式,扩展方法,对象和集合构造器,查询parsing,expression式树,[和]改进的方法types推断。 由于C#团队是2008 .NET版本中资源最为紧缺的团队,因此不包括LINQ并不严格需要的其他types的扩展。
团队确实考虑在C#4中实现扩展属性,并且实际上编写了一个工作原型,但是当他们发现它不能实现WPF团队(这是该function的动机之一)时,它就被放弃了。 Eric Lipper后来表示,他们确实考虑过静态类的扩展方法,但不能certificate实际的好处与实现,testing和维护的成本相反。
解决方法
有可能写一个扩展方法来closures:
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();
但这很丑陋 它需要反思,并且不能支持任何types的智能types,因为任何Type
都可以调用它,这可能不是预期的function。
我相信你的问题的答案是because it doesn't make any sense to extend with static methods
。 引入Extension methods
主要原因不是extending
你不拥有的类。 主要原因是它允许减less方法嵌套在这样的例子:
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
这就是为什么没有这样的要求有静态类的extension
方法。
扩展方法操作对象,而不是类。 如果你想要一个扩展方法来操作一个类,我想你可以这样做:
public static T DoSomething<T>(this T @class) where T:Type { // access static methods via reflection... return @class; }
在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
那么它不但没有落实,而且会造成方法所属的地方混淆? 引入了静态扩展,因为linq在后来的版本中出现,只是为了支持linq以简单的代码方式,静态的扩展是有用的。
静态扩展仅用于使代码更具可读性。 它在运行时或编译时没有意义。