• 第五章 基元类型


    5.1.基元类型和FCL类型

    编译器直接支持的类型是基元类型,int ,long,string等

    FCL:内置类型 一个基元类型必然映射一个FCL类型,不然你的代码怎么执行。

    int->int32, long->int64
    错误认识: int 在32位机器上是32位整数,64位置机器代表64位整数,这是错误的认识。

    还有还多东西感觉用不上就不用记了,实际生产几乎用不到

     

    5.2引用类型和值类型

       字面上所有属于类的都是引用类型,结构、枚举都是值类型。
    别惊讶你对值类型有误解,你所知道的int类型是精准叫法是:隐射System.Int32结构。他们是值类型的一种而不是值类型的全部。

      另外值类型都是隐式密封。无法作为基类出现。想想为啥呢?

      参考下这个设想:

    Animal animal=new Dog(); //正常 Dog 的基类式 Animal    

     Int32 temp_int32= “5”; //正常吗?Int32的基类假如是string 岂不是乱套了

    另外:是可以控制我们类型中的字段布局,通过StructLayoutAttribute特性,就不做更深入的解释了

     说点有用的:

    内存分配:

       值类型分配在线程栈上,应用类型分配在堆上。对CRL初始化不清楚的同学参考下前面几篇文章。

    值类型仅在栈上是给值类型的具体值,

    引用类型则实际内存分配在堆上,并且堆上保留着一个该对象的 对象类型指针、同步索引块、字段、方法、等。栈上的变量仅仅是个地址指向堆上的对象类型指针。

     

    拆箱、装箱:想办法将两种不同类型的对象在内存上的分配方式转化过来即可。

     

    装箱:拷贝栈数据到堆上,并且初始化了 套餐(见本系列第一篇末尾什么套餐定义)返回套餐种的对象类型指针地址。形成装箱。

    Int age=2;     Object age2=age;

     

    拆箱:拷贝内存堆上的未装箱部分即引用对象的实际值到栈上。然后返回

     Object age2=age;  int age=(int)age2;

     

     

    .3.2对象相等性和同一性 简单介绍:

    相等一般指值类型,同一性指引用类型对象指针指向相同。

    System.Object提供了名为Equals的虚方法,作用实在两个对象包含相同值的前提下返回true。因此所有对象都可以重写该方法。

    同一性判定:ReferenceEquals 指出了是否指向了同一个对象。

    其他的讲了一堆实用性门槛高,不做赘述。

     

    额外扩展:ToString()差点漏了个知识点。补上,这个ToString()是一个object的虚方法,凡是调用了基类的虚方法的ToString()就会发生装箱,判定标准是有没有用到 object.ToString();有就装箱。感谢同事 林音小(艺名)的指出

     

    5.4对象哈希码

     对象哈希码相同才能认为是同一个对象,那么重写了Equals方法的对像需要重写对象的hash码,比如 字典类型的对像、Hash table.这句话理解就是不重写 hash code 影响的是依据 hash code 判定是否相等的对象。

    5.5动态类型

    Dynamic  表示对象类型将在运行时解析,平时见到的都是在编译时候解析。

    Dynamic会在最后被解析认为是object类型

    其他的知识不做深入介绍,

    理解和var 的区别 :var 要求编译器能准确推断类型,属于变量命名的一种简写。

    最后别人归纳的笔记好的直接拷贝过来用:

    1.dynamic基元类型是为了方便开发人员使用反射或者与其它非.net组件通信.

    2.代码使用dynamic表达式/变量时,编译器生成特殊的IL代码来描述这种操作。这种特殊的代码被称为payload(有效载荷)。

    3.在运行时,payload根据dynamic表达式/变量引用的对象的实际类型来决定具体执行的操作。

    4.dynamic类型在编译后实际上是作为System.object,然而它在元数据中被应用了System.Runtime.CompilerServices.DynamicAttribute的实例。局部变量除外,因为Attribute显然不能在方法内部使用。

    5.另外使用的泛型的dynamic的代码时,泛型代码已经变异好了,将类型视为Object,编译器不在泛型代码中生成payload,所以也不会执行动态调度。

    6.且编译器允许使用隐式转型语法,将表达式从dynamic转型为其它类型。

    dynamic a=123;

    Int32 b=a;

    7.另外dynamic表达式的求值结果也是一个dynamic类型。

    不能定义对dynamic进行扩展的扩展方法,不能将lambda表达式或匿名方法作为实参传给dynamic使用。

    8.为COM对象生成可由“运行时”调用的包装时。Com组件的方法中使用任何Variant实际都转化为dynamic,这称为动态化。显著简化了与COM对象的操作。

    9.当然用dynamic会有额外的性能开销,因为会引用一些必须的dll,然后执行一些动态绑定啊什么的。如果只是一两处用这个东西,还是用传统方法好一点。(一般会引用Microsoft.CSharp.dll,与com组件操作还会用到System.Dynamic.dll)

     

    这里这位网友没有解释清楚为啥dynamic,会影响性能,使用它时候

    会引用Microsoft.CSharp.dll 这个DLL会间接引用 System.DLL和System.Core.DL而这两个DLL又会间接引用别的DLL。引用就算了,那么为啥会造成性能消耗呢,因为运行是绑定是发生在三大域一个堆中的AppDomian中,这个是我们程序运行的地盘,因此多了会影响程序正常运行,得不偿失。关于什么是三大域一个堆后续再说吧。

  • 相关阅读:
    HDU1263(map)
    Let the Balloon Rise HDU
    PAT甲级1007
    PAT乙级1041
    PAT乙级1037
    PAT乙级1031
    PAT乙级1025
    Hanoi(栈实现)
    《全球资产配置》读后感 读书笔记
    《与内心的恐惧对话》读后感 读书笔记
  • 原文地址:https://www.cnblogs.com/LiMin/p/10792942.html
Copyright © 2020-2023  润新知