第五章 基元类型、引用类型 和 值类型

1. 概述

  本章讨论MS.NET Framework开发人员经常接触到的各种类型。

2. 名词解释

  ① 基元类型:编译器直接支持的数据类型。

  ② 装箱:将一个值类型转换成一个引用类型。

  ③ 拆箱:获取已装箱的对象中的各个字段的地址。

3. 主要内容

  3.1 编程语言的基元类型

    作者建议开发人员开发中使用FCL类型名称,不要使用简化的基元类型名称。原因如下:

    ① 简化名称的映射容易混淆。

    ② 不同的编程语言,规则不一。

    ③ 影响代码的阅读。

    ④ 时间长了容易忘掉多语言环境的支持。

    checked 和 unchecked 基元类型操作。

    两个特殊的类型:System.Decimal 和 System.Numerics.BigInteger .

  3.2 引用类型和值类型

    声明值类型的条件:

    ① 类型具有基元类型的行为。(建议全部字段都标记为readonly)

    ② 类型不需要从其他任何类型继承,也不会派生出其他任何类型。

    ③ 类型的实例较小(<=16b),或者不作为方法的实参传递,也不从方法返回。

    * 用StructLayoutAttribute来控制类型中的字段布局。

  3.3 值类型的装箱和拆箱

    装箱的内部逻辑:

      ① 在托管堆中分配内存。(包括各个字段和两个额外成员-类型对象指针和同步块索引)。

      ② 值类型的字段复制到新分配的堆内存。

      ③ 返回对象的地址。

    拆箱的内部逻辑:

      ① 如果变量为null,抛出 NullReferenceException异常。

      ② 如果类型不符,抛出 InvalidCastException 异常。

      ③ 返回当前对象各个字段的托管堆地址。

    3.3.1 使用接口可以更新已装箱值类型中的字段,但是不建议这么做。

    3.3.2 对象 相等性 和 同一性

      定义自己的类型时,如果要重写Equals,必须确定符合相等性的四个特征:

      ① 自反的。 x.Equals(x)肯定返回true。

      ② 对称的。x.Equals(y)肯定返回与y.Equals(x)相同的值。

      ③ 可传递的。

      ④ 一致的。

      可能还需要:

      ① 让类型实现 System.IEquatable<T>接口的Equals方法。

      ② 重载==和!=操作符方法。

  3.4 对象哈希码

    选择一种算法来计算类型实例的哈希码时,请遵守以下规则:

    ① 这个算法要提供良好的随机分布,使哈希表获得最佳性能。

    ② 可以调用基类的GetHashCode方法并包含它的返回值。不建议调用Object或者ValueType的GetHashCode方法。

    ③ 这个算法应该使用至少一个实例字段。

    ④ 这个算法使用的字段应该是不可变的。

    ⑤ 这个算法应该尽可能快的执行。

    ⑥ 包含相同值的不同对象应返回相同的哈希码。

  3.5 dynamic基元类型

    为了方便开发人员使用反射或者与基本组件通信,C#编译器允许将一个表达式的类型标记为dynamic。

    代码使用dynamic表达式/变量来调用一个成员时,编译器会生成特殊的IL代码来描述所需的操作。这种代码成为payload。

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

4. 总结

  熟练掌握装箱拆箱的机制,有助于写出高效的代码。

原文地址:https://www.cnblogs.com/stone_lv/p/4293081.html