为什么不支持C#静态类扩展方法?

Jus*_*gan 56 c# linq language-design

我从这个问题中知道,扩展方法只能在类实例上运行,而不能在静态类本身上运行.这意味着我无法扩展有用的静态类,如ConvertMath.

我想知道的是,为什么会这样?从上面的链接,有一些关于C#团队如何实现这种功能的建议.是否有一些哲学上的理由不支持它?

例如,这里有一个理由,为什么没有内置的LINQ ForEach<T>扩展IEnumerable<T>.

Eri*_*ert 73

C#团队可以实现这种功能.是否有一些哲学上的理由不支持它?

没有技术原因,也没有哲学原因.然而,正如我经常指出,我没有提供的理由这样做的特征.功能不便宜; 它们非常昂贵,而且它们不仅要证明自己的成本是合理的,而且必须证明没有完成我们本可以用这个预算完成的其他一百个功能的机会成本.我们必须证明我们的利益相关者的功能成本合理,但我们不需要通过实现不符合我们标准的功能来节省时间和精力.

特别是,建议的功能对LINQ没有任何作用; 添加了扩展方法以使LINQ工作.任何没有使LINQ工作的东西都很难进入C#3.0; 我们在时间表上做了大量的工作而没有太多的时间去做.(我很惊讶自动属性使它成功.)在设计它之前削减一个不必要的功能节省了大量的时间和精力花在其他事情不要做LINQ的工作.

简而言之:建议的功能从未满足我们的净成本超过成本的标准,我们总是有更多重要的功能来花费我们有限的时间和精力.

  • @Justin:正确; 我们有"扩展一切"的设计思路 - 构造函数和事件以及整个 - 但如果我们甚至不能适应扩展属性,那么没有太多意义.他们很高兴,但增加的价值不足以证明成本合理. (12认同)
  • @Joan:"琐碎"意味着"我知道该怎么做".从这个意义上说,当然,这是微不足道的; 我们知道我们可以做到.但是琐碎的功能并不一定便宜.我知道如何在亚秒内搜索整个互联网的关键词; 在算法很短的意义上,搜索问题是微不足道的,但实现解决方案的工程问题非常昂贵.没有*廉价*编译器功能.任何功能的设计,实施,测试和维护成本都相当可观.我们必须确保这些好处是相称的. (11认同)
  • 这个非常有趣:非平凡="这意味着不可能.因为没有工程师会承认某些事情是不可能的,所以他们会使用这个词.当工程师说某事是'非平凡'时,它就相当于航空公司飞行员平静地告诉你,你可能会遇到"只是有点动荡",因为他将你带入了一场5级飓风." (8认同)
  • @pst:我们进行功能设计并提出规范草案; 足以写一个原型并开始做测试计划.原型实现和测试显示了规范不足的地方,因此我们相应地改进规范和实现.与建筑师,建筑商和居民共同建造建筑物的鸡和鸡蛋并不是一样的. (6认同)
  • @Joan:这里有一个关于"琐碎"含义的有趣讨论:http://fishbowl.pastiche.org/2007/07/17/understanding_engineers_feasibility/ (2认同)

Jus*_*gan 13

在阅读了答案以及一些相关问题之后,我在这里总结了对这个问题的理解.

扩展方法如何工作

首先,重要的是要认识到扩展只是静态方法的语法糖.

// 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);
Run Code Online (Sandbox Code Playgroud)

该方法实际上不会成为该类的一部分.这就是您无法从扩展方法访问私有成员的原因.扩展方法仅改变C#语法,并且不违反OOP可访问性的概念.实际上,如果你编写一个扩展方法和一个执行相同操作的普通静态方法,那么反编译MSIL,它们完全相同.

为何存在扩展方法

因此,如果他们不添加实际功能,为什么要使用扩展方法呢?答案是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);
Run Code Online (Sandbox Code Playgroud)

在某种程度上,所有LINQ都只是语法糖,因为它可以做的一切都可以用一种笨重的非LINQy方式编写.显然,C#团队认为LINQ获得的可读性是值得的,但它引出了一个问题,"为什么他们会停在那里?"

为什么不是其他扩展类型?

C#编译器开发人员Eric Lippert在博客文章中描述了C#3的很大一部分是创建LINQ所需的所有构造:"隐式类型化本地,匿名类型,lambda表达式,扩展方法,对象和集合初始化器,查询理解,表达式树,[和]改进的方法类型推断." 由于C#团队是2008 .NET版本资源最有限的团队,因此不包括LINQ不是必需的其他类型的扩展.

该团队确实考虑在C#4中实现扩展属性,并且实际上编写了一个工作原型,但是当他们发现它不能使WPF团队实现时(这是该功能的激励因素之一),它被删除了.Eric Lipper后来表示,他们确实考虑过静态类的扩展方法,但无法证明实现,测试和维护成本的真实效益.

解决方法

可以编写一个接近的扩展方法:

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();
Run Code Online (Sandbox Code Playgroud)

但它非常丑陋.它需要反射,并且不能支持任何类型的智能打字,因为任何人Type都可以调用它,这可能不是预期的功能.