一、引言

  在C#中,静态和非静态的特征对于我们来说是再熟悉不过了,但是很少看到有一篇文章去好好地总结静态和非静态它们之间的不同,为了帮助大家更好地去理解静态和非静态特征, 所以将在这篇文章中帮大家全面总结下它们之间的不同,包括静态类,静态成员和静态构造函数。希望在大家巩固基础的时候可以拿出来好好复习下的。下面废话不多了,直接进入我们今天的主题。

二、为什么需要静态特征

  在自定义类或看.NET Framework类库中都可以发现,类中大部分都是具体实例特征(也就是没有static标识的),同时我们也能看到一些具有静态特征的类或成员,例如我们经常使用的Console类以及WriteLine方法就是静态的。然而有些朋友会疑惑,为什么还要有静态特征的呢?干脆都定义为实例的好了? 然后静态特征的存在肯定有它存在的原因的,并不是我们就是要这么定义的,其实我一直认为不管是什么都是源于生活的, 技术的实现也是一样,比如我们开发程序,需要掌握技术外,其实更重要的是业务逻辑这块的,如果你都不知道你开发的东西是怎样的一个流程,即使你技术再牛做出来的东西都是反人类的东西(也就是指不符合用户的用户习惯和之前的一个业务需求),其实静态特征的存在也是源于生活的,对于类好比就是我们现实生活中的人或事物,静态特征和非静态特征就好比生活中人或事物具有的特征, 我们询问人的时候或者电视剧警察查案件的时候,都会听到这样一句话 "那个人有什么特征?"或 “嫌疑犯有什么特征?多高,年龄等” 其实高度、年龄、性别都是一个人的特征,所以这些在语言范畴就需要为其进行定义了,也就是我们定义的实例成员了,然而有些特征需要被所有对象实例所共有的,这些特征在语言范畴就定义为静态特征,具体哪些特征可以定义为静态特征呢? 其实这点一样是源于生活的,所以我们在开发软件的过程中,必不可少的一个流程就是需求分析了,只有在了解客户需求的条件下才能进行之后的所有流程的, 例如一个班级有很多学生,每个学生是一个实体,在语言范畴就可以定义一个类,当我们需要一个学生的时候就可以通过new 关键字创建一个出来(说到这里又让我想到了恶搞泰囧的图片——你有对象吗?没对象,你们程序员可以自己new一个啊?),然而我们创建出来的学生他们都有一些共有的特征,如同一个班级,学校等, 如果我们把班级、学校这样的特征也定义为实例的话,那么我们不是每次创建对象实例的时候都为这些共有的特征分配一次内存的,这样不仅对内存空间的浪费也是不满足生活常识的,此时我们就可以把班级、学校这样的特征定义为静态特征,这样所有实例都可以共享这两个特征,并且不需要为每个对象实例分配内存

三、比较静态特征和非静态特征

3.1 静态类与非静态类

  • 静态类和非静态类在C#中定义基本是一样的,只是静态类定义需要加上static修饰符而已。下面就直接总结下它们之间的区别:
  • 静态类只能包含静态成员,否则会抛出编译错误;然而非静态类既可以包含非静态成员也可以包含静态成员
  • 静态类是不能实例化,之所以不能实例化,是因为静态类会导致C#编译器将该类同时标记为abstract和sealed,并且编译器不会在类型中生成一个实例的构造函数,从而导致静态类不能实例化,具体原因可以见下图;非静态类可以,并且静态成员的访问只能通过类来进行访问,因为静态成员是属于类的。
 public static class StaticClass
{
private static string name;
}

上面代码用IL反汇编程序得到的IL代码结构为:

3.2 静态构造函数与实例构造函数

  • 静态构造函数用来初始化类中的静态成员的,包括静态字段和静态属性,并且静态构造函数是不能带有参数、不能有访问修饰符,静态构造函数的调用是由CLR第一次调用类成员之前执行的。
  • 下面还是直接总结下静态构造函数与实例构造函数之间的区别:
  • 静态构造函数可以与无参的实例构造函数同时存在
  • 静态构造函数在CLR加载类时执行,然而实例构造函数在每次实例创建时都会执行
  • 静态构造函数只能对静态成员初始化,不能对非静态成员进行初始化操作,然而实例构造函数,既可以初始化实例成员也可以初始化静态成员,但静态只读字段除外
  • 静态构造函数只被执行一次,但是CLR也不能确定它什么时候被执行,它的执行方式有两种,precise和before-field-init,这个会在下一篇文章中详细给大家介绍,这里先提出给大家一个思考的空间。而实例构造函数在每次创建对象实例时都会被执行,创建几个就会执行几次
  • 一个类只能有一个静态构造函数,却可以有多个实例构造函数

静态字段的初始值在静态构造函数调用之前被指定,构造函数的执行顺序大致如下图所示:

3.3 静态字段、属性和实例字段、属性

下面就直接总结下它们之间的区别:

  • 静态成员包括静态字段和静态字段,静态字段一般实现为private,静态属性一般实现为public,从而来体现类的封装性
  • 静态成员和类相关联,不依赖于对象而存在,只能由类来访问;实例成员与具体类相关联,只能由对象实例访问
  • 静态成员不管创建多少实例对象,都在内存中只有一份,实例成员每创建一个实例对象,都会在内存中分配一块内存区域。

3.4 静态方法与实例方法

类似于静态字段和属性,静态方法共享代码段,同样以static关键字来标识静态方法,对于他们之间的区别总结为:

  • 静态方法只能访问静态成员和方法,但是可以间接通过创建实例对象来访问实例字段、属性和方法;实例方法既可以访问实例成员也可以访问静态成员
  • 静态方法由类方法‘实例方法由对象访问
  • 静态方法不能引用this关键字,而实例方法可以
  • 静态方法不能被标识为virtual、abstract或override,静态方法可以被派生访问,但是不能被派生类重写
  • Main方法为静态的,所以Main方法不能直接访问类中的实例字段、属性和方法,否则编译器会报错
  • 静态方法一般用于作为通用的工具类来实现
  • 在性能上,静态方法和实例方法的差别不大。因为,它们都是在JIT加载类的时候分配内存的,不同的是静态方法是以类为引用,而实例方法是以对象为引用,创建实例时,不会再为静态方法分配内存,所有实例对象共用一个类的方法代码,所以,静态方法和实例方法的调用,区别仅在于静态方法可以直接调用,而实例方法需要当前对象指针指向该方法,在性能上差不并不大。

四、小结

  到这里,本文章的内容就介绍完了,通过对静态特征和非静态特征的由来来揭开一些都是源于生活的观点,然后再详细分析了静态特征与非静态特征在C#语言中的区别,希望这些总结可以帮助大家在复习基础知识的时候可以有用。同时也是自己的一个复习笔记的。

C#中静态方法和非静态方法的区别(二)的更多相关文章

  1. 转 C#中静态方法与非静态方法区别比较

    C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...

  2. C#中静态方法和非静态方法的区别

    静态方法和非静态方法的区别: 1.静态方法不需要类实例化就可以调用,反之非静态方法需要实例化后才能调用: 2.静态方法只能访问静态成员和方法,非静态方法都可以访问: 3.静态方法不能标记为overri ...

  3. Java中synchronized用在静态方法和非静态方法上面的区别

    synchronized 修饰在 static方法和非static方法的区别   在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...

  4. C#中静态与非静态方法比较

    C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...

  5. C#中静态与非静态方法比较【转】

    C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...

  6. c#静态方法和非静态方法区别

    c#静态方法和非静态方法区别 C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用上会有什么不同呢?让我们来看看最直观的差别:使用了static 修饰符的方法为 ...

  7. Java中堆、栈,静态方法和非静态方法的速度问题

           一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储 ...

  8. 在java中静态方法与非静态方法

    在java中public void与public static void有什么区别 ? public void 修饰是非静态方法,该类方法属于对象,在对象初始化(new Object())后才能被调用 ...

  9. <转>java中静态方法和非静态方法的存储

    Java中非静态方法是否共用同一块内存? 将某 class 产生出一个 instance 之后,此 class 所有的 instance field 都会新增一份,那么所有的 instance met ...

  10. 在静态方法和非静态方法上加 Synchronized的区别

    Synchronzied 修饰非静态方法==>对象锁 Synchronzied 修饰静态方法==>其实是类锁,因为是静态方法,它把整个类锁起来了: 1.Synchronized修饰非静态方 ...

随机推荐

  1. Working XML: Processing instructions and parameters

    Adding support for multiple style sheets This month our hardworking columnist(专栏作家) adds support for ...

  2. hdoj 1596 find the safest road【最短路变形,求最大安全系数】

    find the safest road Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  3. 层层递进Struts1(八)之总结

    先来看一下Struts1学习总结的思维导图,画的主要是Struts1中的重点和博客分布,如下所示: 系列博客的侧重点是: Struts1是什么? 为什么要使用它? 如何使用Struts1? Strut ...

  4. Linux下开启MySQL的远程连接

    今天在用客户端工具远程连接mysql的时候,连接不上,以为是防火墙,关了防火墙后依然打不开,后开在网上查了下原来mysql基于安全考虑root账户一般只能本地访问,但是在开发过程中可能需要打开root ...

  5. 用js判断一个复选框是否被选中

    <html> <head>        <title>            复选框全选.全不选.反选.必选一个        </title>    ...

  6. libcurl 使用的几个注意事项

    注:libcurl 入门指南( the tutorial ): http://curl.haxx.se/libcurl/c/libcurl-tutorial.html 0. 为使用的curl url ...

  7. 新秀学习Hibernate——简单的增加、删、更改、检查操作

    部分博客使用Hibernate单的样例,把数据库的映射显示了出来在上一篇的博客基础上这篇博客讲述怎样利用Hinbernate框架实现简单的数据库操作. 1.增加junit.jar 2.新建一个工具类H ...

  8. 10个精妙的Java编码最佳实践

    这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表.和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不 ...

  9. 两层Fragment嵌套,外层Fragment切换时内层Fragment不显示内容

    尊重他人劳动成果,转载请说明出处:http://blog.csdn.net/bingospunky/article/details/46847269 需求 在搭界面有这么样一个需求:须要两层的Frag ...

  10. QT QXmlStreamWriter用法小结

    一 API介绍 writeStartDocument():写文档头,作用类似于创建一个xml文档,并在文档开头部分写入版本信息和编码信息,一般为: <?xml version="1.0 ...