讨论下何时用静态方法,何时用实例方法。 c#静态方法和实例方法的几种用法,见如下代码:这三种形式我们应该都用过。 public class SomeClass
{ private string myfield =null; public static instance =new SomeClass();//实例化 public instranceMethod() {};//第一种 public static staticMethod() {};//第二种 } public class AnotherClass//三种 { publicstatic Main() { //第一种方式, 声明实例,调用实例方法 SomeClass someClass =new SomeClass(); someClass.instanceMethod(); //第二种方式,通过一个静态的实例,去调用实例方法 SomeClass.instance.instanceMethod(); //第三种方式,直接调用静态方法 SomeClass.staticMethod(); } } 这几种方式在调用时间,还有线程安全,面向对象的编程方面都有差别。后文会谈到。 "静态方法是常驻内存" 这是那位blog作者在评论中给出的观点。我觉得"静态方法是常驻内存"的说法是不对的。要知道一个.net类型的静态方法是属于这个.net类型的。而这个.net类型是一个.net 程序集的一部分。这个.net程序集是被一个AppDomain装入到内存里面来的。这个AppDomain是可以从内存卸载的。一个有.net CLR的进程里面可以有多于一个的AppDomain,第一个AppDomain之后的AppDomain都可以动态创建和卸载。这些AppDomain中的.net程序集,既可以有静态方法,也可以有实例方法。不管是静态方法还是实例方法,都是随其程序集所在的AppDomain一起创建和卸载。第一个AppDomain在整个程序运行结束时也会最后被卸载。其中所含的.net程序集自然也卸载。看图1会更明白点。所以静态方法不存在常驻内存一说。 "静态方法比实例方法先装载" 这也是那篇blog的评论中某些人提出的观点。我不知道他们的论据是什么,但是我已经做过实验,而且也写过这两篇blog关于.net反射和metadata加载--致Jeffray Zhao等几位和firelong和[继续讨论]关于Windows PE和.net assembly的加载来证明.net程序集的加载方式是整个地加载,而不是用到某个metadata才加载该metadata, 用到某个方法才加载该方法。因为静态方法和实例方法同属于一个.net类型,而一个.net类型属于一个.net程序集。在整个地加载一个.net程序集的时候,不管是静态方法还是实例方法,都随该程序集全部加载进内存。所以"静态方法比实例方法先装载"也是不成立的。 何时用静态方法,何时用实例方法。 先说实例方法,当你给一个类写一个方法,如果该方法需要访问某个实例的成员变量时,那么就将该方法定义成实例方法。一类的实例通常有一些成员变量,其中含有该实例的状态信息。而该方法需要改变这些状态。那么该方法需要声明成实例方法。 静态方法正好相反,它不需要访问某个实例的成员变量,它不需要去改变某个实例的状态。我们把该方法定义成静态方法。 第一种方式,声明实例,调用实例方法。 当一个类有多个实例,例如学生这个类,实例可以有学生甲,学生乙,学生丙,等等,我们就用第一种方式。在多线程的情况下,只要每个线程都创建自己的实例,那么第一种方法通常是线程安全的。 第二种方式,通过一个静态的实例,去调用实例方法。 这种情况比较特殊,通常是整个程序里该类唯一的一个实例,我们通过调用该实例的实例方法来改变该实例的某些状态。这一个实例在多线程的情况下,通常是线程不安全的。除非我们给这个实例加锁。防止其他线程访问该实例。 第三种方式,直接调用静态方法。 这种情况下静态方法不需要去改变某个实例的状态。只要得到少量的参数就可完成既定事情。比如判断一个文件是否存在,只要给个文件路径和文件名,就能知道该文件是否存在。 |
|
来自: 悟静 > 《.net和asp.net》