2009-07-26 217 views
29

假设您有一些方法可以在非静态类中进行静态化。
例如:静态与非静态方法

private double power(double a, double b) 
    { 
     return (Math.Pow(a, b)); 
    } 

你看到从改变方法的签名为静态任何好处?在上面的例子:

private static double power(double a, double b) 
    { 
     return (Math.Pow(a, b)); 
    } 

即使有一些性能或记忆的增益,不会编译器做在编译时一个简单的优化?


编辑:我在寻找的是通过声明方法为静态的好处。我 知道,这是常见的做法。我想了解它背后的逻辑。
当然,这种方法只是一个例子来阐明我的意图。

+0

@大家好,我知道这是发展年代的一个“古老”问题,但它今天仍然相关。下面有很多**优秀的**答案。需要您的特定场景的实际性能数字?编写一个快速的程序,调用该方法足够多的时间(在var start = DateTime.Now()和var end = DateTime.Now()之间),以便能够经历足够长的时间以进行比较。用`static`运行几次,没有`static`运行几次并比较差异。也许打开TaskManager并观察每个场景的内存使用情况。 – 2014-11-25 15:12:21

+0

只是为了完整性,而不是比较两个`DateTime.Now()`之间的差异,请使用[`StopWatch`类](https://msdn.microsoft.com/zh-cn/library/system.diagnostics。秒表(v = vs.110)的.aspx)。 编辑 - 为什么?它比'DateTime.Now()`方式更准确,更易于使用。 – 2015-11-18 09:44:06

回答

7

请注意,编译器甚至不允许代表您进行更改,因为它会更改方法的签名。因此,一些精心制作的反射(如果你使用的话)可能会停止工作,编译器真的不知道是否是这种情况。

1

这种方法应该是静态的,因为它是不相关的类或类成员。它只是与这个函数的输入一起工作。

也许您可能需要在不创建该类的情况下调用它。所以如果它是静态的,那么可以,但如果不是这样,你不能在没有该类的任何实例的情况下调用它。在静态方法


优点:

没有必要先创建一个对象。该方法立即可用。

这是一个很好的,当你有一个不依赖于特定对象的状态一般功能。例如,查看Arrays类或java.util的Collections类。

静态方法对工厂很有用。将您的需求作为参数传递,获得一个全新的对象。看不到构造函数。

静态方法的缺点:

你没有一个对象实例,所以你只能访问静态成员和自己的局部变量。如果你想要一个实例,你可能必须自己创建它。

您可以创建子类,但静态方法不能是抽象的,所以这是很难从呼叫者解耦实现。


(PS:我不认为编译器会优化它是否将是静态的或不..但不知道)

33

根据定义,power是无状态的,并且对任何封闭类无副作用所以应该声明为static

article从MSDN进入一些非静态与静态的性能差异。这个调用比实例化和调用快四倍,但它确实只是一个严格的循环,这是一个性能瓶颈。

+0

链接在哪里? – 2009-07-26 14:32:46

+0

@niko:修正。对不起,谢谢。 – jason 2009-07-26 14:33:23

+0

为msdn链接+1。 – 2009-07-26 15:34:22

2

要我一个容易回答的决定是“我应该实例化这个对象只是调用该函数”。在你的功能的情况下,我会说答案是否定的,所以它应该是静态的。这个方法似乎没有关系到你的对象,所以我再次投票静态。

8

如果您将方法声明为静态,应该会有轻微的性能改进,因为编译器将发出call IL指令而不是callvirt

但像其他人说,这应该是静态的,无论如何,因为它不涉及具体的实例

0

我相信,编译器不会优化成一个静态方法这一点。性能提高了,因为不需要检查指针是否在运行时为空。看看FXCop rule以供参考。

1

编译器可能会考虑在它将代码“JITs”缩短的情况下进行内联,如果这样做的话,那么很可能会优化对未使用的此参数的引用。但是你不能依赖任何这些。

你仍然需要创建一个对象才能调用它,除非将其设置为static,否则如果因为其他原因而不需要其中一个,则会有更大的开销。

-5

我希望我们需要定义静态和非静态方法之间的区别。在这里,我发布了几行简单的代码来形象化概念差异。

public class StaticVsNonStatic 
{ 
    public string NonStaticMethod() //non-static 
    { 

     return "I am the Non-Static Method"; 

    } 

    static public string StaticMethod() //static 
    { 

     return "I am Static Method"; 
    } 

} 

现在让我们创建一个aspx页面,尝试访问这两个类中定义的方法。

public partial class StaticVsNonStatic_StaticVsNonWorkplace : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 

     StaticVsNonStatic objStaticVsNonStatic = new StaticVsNonStatic(); 
     lblDisplayNS.Text = objStaticVsNonStatic.NonStaticMethod(); //Non Static 
     lblDisplayS.Text = StaticVsNonStatic.StaticMethod(); //Static and called without object 
    } 
} 

谢谢,请发表评论。

最好的问候,Pritom南迪[孟加拉国]

2

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

3

您是否发现将方法签名更改为静态有任何好处?

三个好处:

  1. 制造无国籍方法静态帮助文档,并澄清自己的目的。否则,人们倾向于担心该方法依赖于什么神秘的状态?

  2. 静态方法可以从其他静态代码调用,因此可能更有用。

  3. 静态方法调用比实例调用具有更少的运行时开销。编译器不能自动进行转换 - 一个原因是因为它会影响null的使用。即使在方法中没有使用实例状态,也需要在空引用上调用该方法以失败并返回NullReferenceException。