深入理解C#(八)

*第二章(C# 类型系统)

C# 1的类型系统是静态的、显示的和安全的

静态:描述表达式的编译时类型,使用不变的数据来分析哪些操作可用。

C# 1的类型系统何时不够用

.NET 1.1内建了三种集合类型:

  • 数组–强类型–内建到语言和运行时中
  • System.Collections命名空间中的弱类型集合
  • System.Collections.Specialized命名空间中的强类型集合

引用类型的数组支持协变(covariance),只要元素的类型之间允许转换,就能隐式将一种数组类型转换成另一种

方法覆盖和接口实现不允许协变性/逆变性

参数类型的逆变性:使用一个放宽限制的签名如:void Process(object x)

值类型和引用类型

类是引用类型;结构是值类型

数组是引用类型;枚举是值类型

委托类型是引用类型;接口类型是引用类型,但可由值类型实现

变量存储

  1. 变量的值在它声明时的位置存储
  2. 局部变量的值总是存储在栈(stack)中(C# 1中完全成立,高级版本可能存在堆中)
  3. 实例变量的值总是存储在实例本身存储的地方
  4. 引用类型实例总是存储在堆(heap)中,静态变量也是。

关于引用传递和值传递

无论是引用传递还是值传递,永远不会传递对象本身。
详见Parameter passing in C#

关于装箱和拆箱

  • 对于引用类型的变量,它的值永远是一个引用

  • 对于值类型的变量,它的值永远是该值类型的一个值

    int i=5;
    object o=i;
    int j=(int) o;

第二行,发生了装箱操作:运行时在堆上创建一个包含值(5)的对象,o的值是对该新对象的一个引用。该对象的值是原始值的一个副本,改变i不会改变箱内的值。

第三行,执行相反操作,拆箱。必须告诉编译器将object拆箱成什么类型。

装箱什么时候方式?

为一个类型的值调用ToString、Equals或GetHashCode方法时,如果该类型没有覆盖这些方法,也发生装箱。另外,将值作为接口表达式使用时也会发生装箱。

太过频繁的装拆箱会增大程序的操作开销,还会创建数量众多的对象,加重垃圾回收器的负担。