C#类 - 为什么这么多静态方法?

时间:2011-10-24 01:30:05

标签: c#

我对C#很陌生,所以请耐心等待。

我注意到关于C#的第一件事是许多类都是静态方法。例如......

为什么:

Array.ForEach(arr, proc)

而不是:

arr.ForEach(proc)

为什么会这样:

Array.Sort(arr)

而不是:

arr.Sort()

随时在网上给我一些常见问题解答。如果在某个地方的某本书中有详细的答案,我也欢迎指向它的指针。我正在寻找关于此的明确答案,但您的推测值得欢迎。

6 个答案:

答案 0 :(得分:11)

因为那些是实用程序类。考虑到C#中没有自由函数,类构造只是将它们组合在一起的一种方式。

答案 1 :(得分:8)

假设this answer正确,实例方法需要“方法表”中的额外空间。使数组方法静态化可能是一个早期节省空间的决定。

这一点,以及避免Amitd引用的this指针检查,可以为像数组这样无处不在的东西提供显着的性能提升。

答案 2 :(得分:5)

另请参阅FXCOP

中的此规则

CA1822: Mark members as static

  

规则说明

     

不访问实例数据或调用实例方法的成员可以   被标记为静态(在Visual Basic中共享)。标记后   方法为静态,编译器将发出非虚拟调用站点   这些成员。发送非虚拟呼叫站点将阻止检查   每次调用的运行时确保当前对象指针   是非null。这可以实现可测量的性能增益   性能敏感的代码。在某些情况下,无法访问   当前对象实例表示正确性问题。

答案 3 :(得分:1)

反对静态的经典动机:

  1. 难以测试
  2. 不是线程安全的
  3. 增加内存中的代码大小
  4. 1)C#有几种工具可以使测试静态方法相对容易。 C#模拟工具的比较,其中一些支持静态模拟:https://stackoverflow.com/questions/64242/rhino-mocks-typemock-moq-or-nmock-which-one-do-you-use-and-why

    2)有一些众所周知的高效方法可以在不损失C#中的线程安全的情况下进行静态对象创建/逻辑。例如,在C#中使用静态类实现Singleton模式(如果选项不合适,您可以跳转到第五种方法):http://www.yoda.arachsys.com/csharp/singleton.html

    3)正如@ K-ballo所提到的,每种方法都有助于C#中内存中的代码大小,而不是实例方法得到特殊处理。

    那就是说,你指出的两个具体例子只是静态数组类的遗留代码支持问题,然后在C#1.0天内引入泛型和其他一些代码糖,正如@Inerdia所说。我试图回答假设您有更多的代码,可能包括外部库。

答案 4 :(得分:1)

感知功能。

“实用程序”功能与OO旨在定位的大部分功能不同。

考虑集合,I / O,数学和几乎所有实用程序的情况。

使用OO,您通常可以为您的域建模。这些东西都不适合你的领域 - 它不像你正在编码并且去“哦,我们需要订购一个新的哈希表,我们的东西已经满了”。实用的东西往往不适合。

我们非常接近,但是传递集合仍然不是很好(你的业务逻辑在哪里?你在哪里设置操纵你的集合的方法,以及你总是传递的其他一小部分或两个数据吗?)

与数字和数学相同。拥有Integer.sqrt()和Long.sqrt()以及Float.sqrt()是很困难的 - 它只是没有意义,也不是“new Math(。。sqrt()”。有很多领域它没有很好的模型。如果您正在寻找数学建模,那么OO可能不是您最好的选择。 (我在Java中创建了一个非常完整的“Complex”和“Matrix”类并使它们相当OO,但是让它们真正教会了我OO和Java的一些限制 - 我最终“使用”Groovy中的类主要是)

我从来没有见过像OO那样的任何东西,可以用来建模业务逻辑,能够演示代码之间的联系以及管理数据和代码之间的关系。

所以当我们更有意义时,我们会回到不同的模型上。

答案 5 :(得分:0)

Array类不是通用的,不能完全通用,因为这会破坏向后兼容性。在数组实现IList<T>的地方有一些魔力,但这只适用于下限为0的单维数组 - “list-ish”数组。

我猜测静态方法是添加适用于任何形状数组的泛型方法的唯一方法,无论它是否符合上述编译器魔法。