本文将围绕c#静态方法和实例方法讨论一下针对一些观点如静态方法是常驻内存 还有静态方法比实例方法先装载做一个辨析同时讨论下何时用静态方法何时用实例方法
前几日在微软的好友发给我一个链接《静态方法和实例化方法之间的区别你知道了嘛? 欢迎讨论!! 问题最终 》然后说这里某些观点需要澄清一下希望我写一篇blog我当时读了这篇blog 文比较短列举了静态方法和实例方法的几种案例也没有论点然后就请大家讨论后面评论就比blog热闹多了言辞也激烈后来该blog作者干脆把这篇blog删了现在已经看不到这篇blog了现在我写这篇blog一是针对一些观点做个辨析二是完成好友的所托
c#静态方法和实例方法的几种用法
见如下代码这三种形式我们应该都用过
view sourceprint? public class SomeClass
{
private string myfield = null;
public static instance = new SomeClass();
public instranceMethod() {};
public static staticMethod() {};
}
public class AnotherClass
{
public static Main()
{
//第一种方式 声明实例调用实例方法
SomeClass someClass = new SomeClass();
someClassinstanceMethod();
//第二种方式通过一个静态的实例去调用实例方法
SomeClassinstanceinstanceMethod();
//第三种方式直接调用静态方法
SomeClassstaticMethod();
}
}
这几种方式在调用时间还有线程安全面向对象的编程方面都有差别后文会谈到
静态方法是常驻内存
这是那位blog作者在评论中给出的观点我觉得静态方法是常驻内存的说法是不对的要知道一类型的静态方法是属于这类型的而这类型是一 程序集的一部分这程序集是被一个AppDomain装入到内存里面来的这个AppDomain是可以从内存卸载的一个 CLR的进程里面可以有多于一个的AppDomain第一个AppDomain之后的AppDomain都可以动态创建和卸载这些AppDomain中程序集既可以有静态方法也可以有实例方法不管是静态方法还是实例方法都是随其程序集所在的AppDomain一起创建和卸载第一个AppDomain在整个程序运行结束时也会最后被卸载其中所含程序集自然也卸载看图会更明白点所以静态方法不存在常驻内存一说
图
静态方法比实例方法先装载
这也是那篇blog的评论中某些人提出的观点我不知道他们的论据是什么但是我已经做过实验而且也写过这两篇blog关反射和metadata加载致Jeffray Zhao等几位和firelong和[继续讨论]关于Windows assembly的加载来证程序集的加载方式是整个地加载而不是用到某个metadata才加载该metadata 用到某个方法才加载该方法因为静态方法和实例方法同属于一类型而一类型属于一程序集在整个地加载一程序集的时候不管是静态方法还是实例方法都随该程序集全部加载进内存所以静态方法比实例方法先装载也是不成立的
何时用静态方法何时用实例方法
先说实例方法当你给一个类写一个方法如果该方法需要访问某个实例的成员变量时那么就将该方法定义成实例方法一类的实例通常有一些成员变量其中含有该实例的状态信息而该方法需要改变这些状态那么该方法需要声明成实例方法
静态方法正好相反它不需要访问某个实例的成员变量它不需要去改变某个实例的状态我们把该方法定义成静态方法
第一种方式 声明实例调用实例方法
当一个类有多个实例例如学生这个类实例可以有学生甲学生乙学生丙等等我们就用第一种方式在多线程的情况下只要每个线程都创建自己的实例那么第一种方法通常是线程安全的
第二种方式通过一个静态的实例去调用实例方法
这种情况比较特殊通常是整个程序里该类唯一的一个实例我们通过调用该实例的实例方法来改变该实例的某些状态这一个实例在多线程的情况下通常是线程不安全的除非我们给这个实例加锁防止其他线程访问该实例
第三种方式直接调用静态方法
这种情况下静态方法不需要去改变某个实例的状态只要得到少量的参数就可完成既定事情比如判断一个文件是否存在只要给个文件路径和文件名就能知道该文件是否存在