代码改变世界

《CLR.via.C#第三版》第二部分第4,5章节读书笔记(二)

2014-11-07 13:26  杭伟  阅读(978)  评论(0编辑  收藏  举报

这两章全是理论性的东西,我觉得不必过于钻牛角尖。理论这东西,只有在长期的实践中去慢慢领悟才会深刻。下面我只写些我认为重要的关键知识。

(一)类型转换

知识点:向基类型的转换被认为是一种安全的隐式转换;向派生类型转换时,只能显示转换。

举例:

Object o = new Employee();
Employee e = (Employee)o;

重要认知:CLR的类型检查会遍历继承层次结构,用每个基类型去核对指定的类型。

常用代码:(见下方代码段。CLR会检查两次对象的类型):

if(o is Employee){
      Employee e = (Employee)o;            
}

简化代码:(见下方代码段。CLR会检查一次对象的类型)

Employee e = o as Employee;
if(e != null){
     //...
}

(二)值类型和引用类型

重要认知:1.栈中储存的是值类型、引用类型的指针(地址);堆中存储引用类型本身(不全是,见2)。

              2.包含在引用类型内的值类型不会被存储在栈中,而是堆中(还是值类型,未被装箱),它被包含于引用类型对象中。

(三)重视装箱和拆箱对程序性能的影响

理解以下代码中的三次装箱:

public static void Main(){
      Int32 v=5;
      Object o =v;
      v=123;
      Console.WriteLine(v + ", " + (Int32)o );
}

第一次装箱是将v转换成object对象;第二次和第三次是因为WriteLine()方法要获取一个String对象,这样v和被拆箱的o会被再次装箱。

“装箱”发生的事情:

1. 在托管堆中分配内存,包括值类型字段需要的内存量+类型对象指针的内存量+同步块索引需要的内存量。

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

3. 返回对象的地址。(地址是对对象的引用(指针),值类型变成引用类型)

概念应用:

重写类中的ToString()方法,可以避免使用ToString()方法时的装箱问题。

public class A
{
      private int x;
      public override String ToString()
      {
            return string.formart("{0}",x);
      }
}

注意重写的ToString()方法内部如果调用了base.ToString();外部调用此方法时,值类型依然会被装箱。