zoukankan      html  css  js  c++  java
  • 第四章 类型基础

    4.1 所有类型都从System.Object派生

    "运行时"要求每个类型最终都从System.Object类型派生。

    System.Object 公共实例方法:

    Equals:如果两个对象具有相同的值,就返回true。

    GetHashCode:返回对象的值得哈希码。如果某个类型的对象要在哈希表集合中作为建使用,类型应该重写改方法。方法应该为不同对象提供良好分布。

    ToString:默认返回类型的完整名称(this.GetType().FullName)。但经常重写改方法来返回包含对象状态表示的String对象。

    GetType:返回从Type派生的一个类型的实例,指出调用GetType的那个对象时什么类型。返回的Type对象可以和反射类配合,获取与对象的类型有关的元数据信息。GetType是非虚方法,目的是防止类重写该方法。隐藏其类型,进而破坏类型的安全性。

    受保护方法:

    MemberwiseClone:这个非虚方法创建类型的新实例,并将新对象的实例字段设与this对象的实例字段完全一致。返回对新实例的引用。

    Finalize:在垃圾回收器判读对象应该作为垃圾被回收之后,在对象的内存被实际回收之前,会调用这个虚方法。需要在回收内存前执行清理工作的类型应该重写该方法。

    new操作符:CLR要求所有对象都用new操作符创建。

    1.计算类型及其所有基类型(一直到System.Object)中定义的所有实例字段需要的字节数。堆上每个对象都需要一些额外的成员(overhead成员:开销成员),类型对象指针和同步块索引。CLR利用这些成员管理对象。额外成员的字节数要计入对象大小。

    2.从托管堆中分配类型要求的字节数,从而分配对象的内存。分配的所有字节都设为零(0)。

    3.初始化对象的“类型对象指针”和“同步块索引”。

    4.调用类型的实例构造器,传递在new调用中指定的实参。大多数编译器都在 构造器中自动生成代码来调用基类构造器。每个类型的构造器都负责初始化类型定义的实例字段。最终调用System.Object的构造器,该构造器没有实例字段,什么都不做,简单地返回。

    new执行了所有这些操作后,返回指向新建对象的一个引用(或指针)。

    4.2 类型转换

    CLR最重要的特性之一就是类型安全。

    CLR允许将对象转换为它的实际类型或者它的任何基类型。

    is和as操作苻

    is检查对象是否兼容于指定类型,返回Boolcan值true或false。is操作符永远不抛出异常。如果对象引用为null,is操作符总是返回false。

    as操作符的工作方式与强制类型转换一样,只是它永远不抛出异常,如果对象不能转型,结果就是null。

    4.3 命名空间和程序集

    命名空间对相关的类型进行逻辑分组,开发人员可通过命名空间方便地定位类型。

    using指令:减少打字量,允许为类型或命名空间创建别名。

    4.4 运行时的相互关系

    进程可能有多个线程,线程创建时会分配到1MB的栈。栈空间用于向方法传递实参,方法内部定义的局部变量也在栈上。栈从高位内存到低位内存地址构建。

      最简单的方法包含“序幕”代码,在方法开始做工作前对其进行初始化;还包含“尾声”代码,在方法做完工作后对其进行清理,以便返回至调用者。

    调用方法时,会把作为实参的局部变量中的地址压入栈,用被调用的方法的形参变量标志栈位置。 还会将“返回地址”压入栈。被调用的方法在结束之后返回至该位置。

      JIT编译器将方法中的IL代码转换成本机CPU指令时,会注意到方法内部引用的所有类型。这时CLR要确认定义了这些类型的所有程序集都已加载。然后利用程序集的元数据,CLR提取与这些类型相关的信息,创建一些数据结构(在堆中)来表示类型本身。(类型对象使用的数据结构)

    定义类型时,可在类型内部定义静态数据字段。为这些静态数据字段提供支援的字节在类型对象自身中分配。每个类型对象最后都包含一个方法表(MethodDef方法表),方法表中类型定义的每个方法都有对应的记录项。

    当CLR确认方法需要的所有类型对象都已创建后,方法的代码已经编译之后,就允许线程执行方法的本机代码。

      序幕代码在执行时必须在线程栈中为局部变量分配内存,作为方法“序幕”代码的一部分,CLR自动所有局部变量初始化为null和0。如果代码试图访问尚未显示初始化的局部变量,C#会报告错误消息:使用了未赋值的局部变量。然后构造对象(类型实例)包含类型对象指针和同步块索引以及实例字段。任何时候在堆上新建对象,CLR都自动初始化内部“类型对象指针”成员来引用和对象对应的类型对象。在调用类型的构造器之前,CLR会先初始化同步块索引,并将对象的所有实例字段设为null或0。new操作符返回对象的内存地址。

    调用静态方法时:CLR会定位与定义静态方法的类型对应的类型对象。然后JIT编译器在类型对象的方法表中查找与被调用方法对应的记录项,对方法进行JIT编译,在调用编译好的代码。在内部,静态方法在堆上构造一个新的对象,和返回对象地址并保存到变量中。

    调用非虚实例方法时:编译器会找到与“发出调用的那个变量的类型”对应的类型对象。如果类型没有定义正在调用的那个方法,JIT会回溯类层次结构(一直回溯到System.Object),并在沿途的每个类型中查找该方法。然后JIT在类型的对象的方法表中查找引用了被调用方法的记录项,对方法进行JIT编译(如果需要的话),再调用JIT编译好的代码。

    调用需实例方法时:JIT编译器要在方法中生成一些额外的代码;方法每次调用都会执行这些代码。这些代码首先检查发出调用的变量,并跟随地址来到发出调用的变量。然后,代码检查对象内部的“类型对象指针”成员,该成员指向对象的实际类型。然后代码在类型对象的方法表中查找引用了被调用方法的记录项,对方法进行编译,再调用。

      类型对象本质上也是对象。CLR创建类型对象时,必须初始化这些成员。CLR开始在一个进程中运行时,会立即为MSCorLib.dll中定义的System.Type类型创建一个特殊的类型对象。所有类型对象都是该类型的“实例”。对象中的类型对象指针成员会初始化成对System.Type类型对象的引用。

      System.Type类型对象本身也是对象,内部“类型对象指针”指向它本身,因为System.Type类型对象本身也是一个类型对象的“实例”。System.Object的GetType方法返回存储在指定对象的“类型对象指针”成员中的地址。也就是说,GetType方法返回指向对象的类型对象指针。这样就可以判断系统中任何对象的真实类型。

    每天学习一丢丢
  • 相关阅读:
    win7 下 qwt安装教程
    qt里标识操作系统的宏
    qt 获取系统磁盘空间大小
    qwt总结1
    debian创建apt-proxy代理
    在Linux使用mingw32来编写win32程序
    Linux环境变量的修改(永久,暂时)
    debian7 oracle11g 解决 link binaries 错误方案
    l​i​n​u​x添加​修​改​用​户​名​密​码
    HOWTO install Oracle 11g on Ubuntu Linux 12.04 (Precise Pangolin) 64bits
  • 原文地址:https://www.cnblogs.com/terry-1/p/9740424.html
Copyright © 2011-2022 走看看