代码改变世界

5.3.1 使用接口更改已装箱值类型中的字段(以及为什么不应该这样做)

2012-01-05 10:21 by iRead, 405 阅读, 0 推荐, 收藏, 编辑
摘要:下面让我们通过一些例子来验证自己对值类型、装箱和拆箱的理解程度。请研究以下代码,判断它会在控制台上显示什么: using System; //Point是一个值类型 internal struct Point{ private Int32 m_x,m_y; public Point(Int32 x,Int32 y){ m_x = x; m_y = y; } public void Change(Int32 x,Int32 y){ m_x = x; m_y = y; } public override Stri... 阅读全文

5.3 值类型的装箱和拆箱

2012-01-04 17:00 by iRead, 710 阅读, 0 推荐, 收藏, 编辑
摘要:值类型是比引用类型更“轻型”的一种类型,因为它们不作为对象在托管堆中分配,不会被垃圾回收,也不通过指针来引用。但在许多情况下,都需要获取对值类型的一个实例的引用。例如,假定要创建一个ArrayList对象(System.Collections命名空间中定义的一个类型)类容纳一组Point结构,那么代码可能像下面这样: //声明一个值类型 struct Point{ public Int32 x,y; } public sealed class Program{ public static void Main(){ ArrayList a = new Array... 阅读全文

5.2 引用类型和值类型

2012-01-03 11:25 by iRead, 275 阅读, 0 推荐, 收藏, 编辑
摘要:CLR支持两种类型:引用类型和值类型。虽然FCL中的大多数类型都是引用类型,但程序员用的最多的还是值类型。引用类型总是从托管堆上分配的,C#的new操作符会返回对象的内存地址—也就是指向对象数据的内存地址。使用引用类型时,必须注意到一些性能问题。首先考虑以下事实:内存必须从托管堆上分配对上分配的每个对象都有一些额外的成员,这些成员必须初始化对象中的其他字节(为字段而设)总是设为零从托管堆上分配一个对象时,可能强制执行一次垃圾收集操作 如果所有类型都是引用类型,引用程序的性能将显著下降。设想假如每次使用一个Int32值时,都进行一次内存分配,性能会受到多么大的影响!为了提升简单的、常用的类... 阅读全文

5.1.1 checked和unchecked基元类型操作

2011-12-30 10:52 by iRead, 434 阅读, 0 推荐, 收藏, 编辑
摘要:对基元类型执行的许多算术运算都可能造成溢出: Byte b = 100; b = (Byte) (b+200) ; //b现在包含44(或者十六进制值2C)重要提示:执行上述算术运算时,第一步要求所有操作数都扩大为32位值(或者64位值,如果任何操作数需要超过32位来表示的话)。所以,b和200(这两个值都不超过32位)首先转换成32位值,然后加到一起。结果是一个32位值(十进制300,或十六进制12C)。该值在存回变量b之前,必须转型为一个Byte。C#不会隐式执行这个转型操作,这正是第二行代码需要强制转换为Byte的原因。 在大多数变成情形中,这种情悄悄发生的溢出是我们不希望的。... 阅读全文

5.1 编程语言的基元类型

2011-12-23 10:23 by iRead, 313 阅读, 0 推荐, 收藏, 编辑
摘要:某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操作它们。例如,可以使用以下语法来分配一个整数: System.Int32 a = new System.Int32(); 但你肯定不愿意使用这种语法来声明并初始化一个整数,它实在是太繁琐了。幸运的是,包括C#在内的许多编译器都允许换用如下所示的语法: int a = 0; 这种语法不仅增强了代码的可读性,而且生成的IL代码与使用System.Int32时生成的IL代码是完全一致的。编译器直接支持的数据类型成为基元类型(primitive type)。基元类型直接映射到Framework类库(FCL)中存在的类型。比如在C... 阅读全文

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

2011-12-23 10:19 by iRead, 247 阅读, 0 推荐, 收藏, 编辑
摘要:本章内容:编程语言的基元类型引用类型和值类型值类型的装箱和拆箱对象哈希码Dynamic基元类型 本章将讨论Microsoft.NET Framework开发人员经常会接触到的各种类型。所有开发人员都应该熟悉这些类型的不同行为。我首次接触.NET Framework时,并不完全理解基元类型、引用类型和值类型的区别,则造成我在代码中会不知不觉引入一些不易察觉的bug和性能问题。通过解释类型之前的区别,希望开发人员能避免我所经历过的麻烦,并提高代码效率。 阅读全文

4.4 运行时的相互联系

2011-12-22 16:36 by iRead, 291 阅读, 0 推荐, 收藏, 编辑
摘要:本节将解释类型、对象、线程栈和托管堆在运行时的相互关系。此外,还将解释调用静态方法、实例方法和虚方法的区别。首先从一些计算机基础知识开始。 虽然下面要讨论的东西不是CLR特有的,但掌握了这些只是之后,就有了一个良好的理论基础。接着,就可以修改我们的讨论,介绍CLR特有的内容。 图4-2展示了已记载了CLR的一个Microsoft Windows进程。在这个进程中,可能存在多个线程。一个线程创建时,会分配到一个1MB大小的栈。这个栈的空间用于向方法传递实参,并用于方法内部定义的局部变量。图4-2展示了一个线程的栈内存(右侧)。栈是从高位内存地址向低位内存地址构建的。在图中,线程已执行了一... 阅读全文

4.3 命名空间和程序集

2011-12-09 10:10 by iRead, 611 阅读, 0 推荐, 收藏, 编辑
摘要:命名空间(namespace)用于对相应的类型进行逻辑性分组,开发人员使用命名空间来方便地定位一个类型。例如,System.Text命名空间定义了一组执行字符串处理的类型,而System.IO命名空间定义了一组I/O操作的类型。下面构造一个System.IO。FileStream对象和一个System.Text。StringBuilder对象:public sealed class Program{ public static void Main(){ System.IO.FileStream fs = new System.IO.FileStream(…); System.... 阅读全文

4.2 类型转换

2011-12-08 10:33 by iRead, 291 阅读, 0 推荐, 收藏, 编辑
摘要:CLR最重要的特征之一就是类型安全性。在运行时,CLR总是知道一个对象是什么类型。调用GetType方法,总是知道一个对象确切的类型是什么。由于这个方法是非虚方法,所以一个类型不可能伪装成另一个类型。例如:Employee类型不能重写GetType方法,并返回一个SuperHero类型。 开发人员经常需要将一个对象从一种类型转换为其他各种类型。CLR允许将一个对象转换为它的(实际)类型或者它的任何基类型。每种编程语言都规定了开发人员具体如何进行这种转型操作。例如,C#不要求任何特殊语法即可将一个对象转换为它的任何基类型,因为向基类型的转换被认为是一种安全的隐式转换。然而,将对象转换为它的... 阅读全文

4.2.1 使用C#的is和as操作符来转型

2011-12-08 10:21 by iRead, 325 阅读, 0 推荐, 收藏, 编辑
摘要:在C#语言中进行类型转换的另一种方式是使用is操作符。is检查一个对象是否兼容于指定的类型,并返回一个Boolean值:true或false。注意is操作符永远不会抛出异常,以下代码进行了演示: Object o = new Object(); Boolean b1 = (o is Object); //b1为true. Boolean b2 = (o is Employee);//b2为false. 如果对象引用是null,is操作符总是返回false,因为没有可检查其类型的对象。is操作符通常像下面这样使用: if (o is Employee){ Employee e... 阅读全文