第五章 基元类型

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中,这个是我们程序运行的地盘,因此多了会影响程序正常运行,得不偿失。关于什么是三大域一个堆后续再说吧。

posted on 2019-04-29 21:15  无觉-李敏  阅读(197)  评论(0编辑  收藏  举报