[CLR via C#]引用类型和值类型

一、引用类型与值类型的区别

CLR支持两种类型:引用类型和值类型。引用类型总是从托管堆上分配的,C#的new操作符会返回对象的内存地址。使用引用类型时,必须注意到一些性能问题。

1)内存必须从托管堆上分配。

2)堆上分配的每个对象都有一些额外的成员(类型对象指针和同步索引块),这些成员必须初始化。

3)对象中的其他字节(为字段而设)总是设为零。

4)从托管城市化上分配一个对象时,可能强制执行一次垃圾收集操作。

为了提升简单的、常用的类型的性能,CLR提供了名为"值类型"的轻量级类型。值类型的实例一般在线程栈上分配(虽然也可以作为字段嵌入一个引用类型的对象中)。在代表值类型的实例中,并不包含一个指向实例的指针。相反,变量中包含了实例本身的字段。由于变量已经包含了实例的字段,所以为了操作实例中的字段,不再需要提取一个指针。值类型的实例不受垃圾回收器的控制。因此,值类型的使用缓解了托管堆中的压力,并减少了一个应用程序在其生存期内需要进行的垃圾回收次数。

二、将类型声明为值类型的条件

设计自己的类型时,要仔细地考虑是否应该将一个类型定义成值类型,而不是定义成引用类型。某些时候,值类型能提供更好的性能。具体地说,除非以下所有条件满足,否则不应该将一个类型声明为值类型。

1)类型具有基元类型的行为。换言之,这是一个十分简单的类型,其中没有成员会修改类型的任何实例字段。建议将值类型的全部字段声明为readonly。

2)类型不需要从其他任何类型继承。

3)类型也不会派生出其他任何类型。

类型实例的大小也应在考虑之列。因为在默认情况下,实参是以传值方式传递的,这会造成对值类型实例中的字段进行复制,从而损害性能。同样地,被定义成返回一个值类型的一个方法在返回时,实例中的字段会复制到调用者分配的内存中,从而损害性能。

三、值类型的优势与劣势

值类型的主要优势在于它们不作为对象在托管堆上分配。当成,与引用类型相比,值类型也存在自身的一些局限。

1)值类型对象有两种表示形式:未装箱和已装箱形式。

2)由于不能将一个值类型作为基类型来定义一个新的值类型或者一个新的引用类型,所以不应该在值类型中引入任何新的虚方法。所以方法都不能是抽象的,而且所有方法都隐式地为密封方法。

3)将一个值类型的变量赋值给另一个值类型变量,会执行一次逐字段的复制。将引用类型的变量赋给另一个引用类型的变量时,只复制内存地址。

时间: 2024-08-28 15:53:59

[CLR via C#]引用类型和值类型的相关文章

CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1; 等价于: int a = 1; 这种语法不仅增强了代码的可读性,其生成的IL代码与使用System.Int32时生成的IL代码是完全一致的. 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到Framework类库(FCL)中存在的类型.如C#中,int直接映射

CLR VIA C#: 基元类型、 引用类型 和 值类型

一.基元类型 . 引用类型 和 值类型的区别: 1.基元类型(primitive type):编译器直接支持的数据类型: 基元类型 直接映射到 FCL 中存在的类型. C# 小写是基元类型,例如:string ,  大写是FCL类型,例如String,  基元类型直接映射到FCL类型,所以这两者之间没有区别,一模一样,不用纠结使用哪种方式了. 支持 直接使用FCL类型, 不使用基元类型, Float 对应 Single FCL类型: dynamic 对应  System.Object FCL类型

读经典——《CLR via C#》(Jeffrey Richter著) 笔记_引用类型和值类型(二)

[引用类型和值类型的区别] //引用类型(由于使用了‘class’) class SomeRef { public Int32 x; } //值类型(由于使用了‘struct’) struct SomeVal { public Int32 x; } static void ValueTypeDemo() { SomeRef r1 = new SomeRef(); //在堆上分配 SomeVal v1 = new SomeVal(); //在栈上分配 r1.x = 5; //提另指针 v1x =

C# 引用类型和值类型

1.引用类型 FCL(Framework)中的大多数类型都是引用类型,引用类型总是在托管堆中分配的,C#的new操作符会返回对象的内存地址,也就是指对象数据的内存地址.在使用引用类型时,存在以下性能问题,这是我们在开发中必须要注意的: a.内存必须从托管堆上分配(也就是说每new一个对象,会占用内存,对象过多就会导致内存占用) b. 堆上分配的每个对象都有一些额外的成员,这些成员必须初始化 c.对象中的其他字节(为字段而设),总是设为0 d.从托管堆中每分配一个对象,可能强制执行一次垃圾回收操作

【转】c#引用类型与值类型的区别大盘点

解析:CLR支持两种类型:值类型和引用类型.用Jeffrey Richter(<CLR via C#>作者)的话来说,“不理解引用类型和值类型区别的程序员将会把代码引入诡异的陷阱和诸多性能问题”.这就要求我们正确理解和使用值类型和引用类型. 值类型包括C#的基本类型(用关键字int.char.float等来声明),结构(用struct关键字声明的类型),枚举(用enum关键字声明的类型):而引用类型包括类(用class关键字声明的类型)和委托(用delegate关键字声明的特殊类).C#中的每

5.基元类型、引用类型和值类型

5.1 基远类型 编译器直接支持的数据类型称为基远类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; //方便的语法 int c = new int(); //不方便的语法 System.Int32 d = new System.Int32(); //最不方便的语法 C#基元类型与对应的FCL类型 C#中的基元类型 FCL类型 是否与CLS兼容 描述 sbyte System.SByte N 有符

引用类型和值类型

CLR支持两种类型:引用类型和值类型. 虽然FCL中大多数都是引用类型,但开发人员用的最多的还是值类型.引用类型总是在托管堆上分配的,C#的new操作符会返回对象的内存地址——也就是指向对象数据的内存地址. 使用引用类型必须注意到一些性能问题,首先考虑一下事实: 1)内存必须从托管堆上分配. 2)对上分配的每个对象都有一些额外的成员(比如前面提到过得"类型对象指针"和"同步块索引"),这些成员必须初始化. 3)对象中的其他字节(为字段而设)总是设为零. 4)从托管堆

c# 引用类型与值类型的区别有哪些

解析:CLR支持两种类型:值类型和引用类型.用Jeffrey Richter(<CLR via C#>作者)的话来说,“不理解引用类型和值类型区别的程序员将会把代码引入诡异的陷阱和诸多性能问题”.这就要求我们正确理解和使用值类型和引用类型. 值类型包括C#的基本类型(用关键字int.char.float等来声明),结构(用struct关键字声明的类型),枚举(用enum关键字声明的类型):而引用类型包括类(用class关键字声明的类型)和委托(用delegate关键字声明的特殊类).C#中的每

Int[]是引用类型还是值类型

分析问题 .NET所有数据都以类型的方式表示,数组也不例外.存储不同类型项目的数组都是一个类型,.NET会自动地为数组生成新的类型.例如下列申明: DateTime[] times; CLR就会在运行时创建一个DateTime[]类型,所以数组类型可以说是一个类型族,而它们的共性就是所有的数组类型继承自System.Array,这种设计方式和委托非常类似,委托的概念将在后面的章节有所覆盖.System.Array实现了多个接口,并且直接继承自System.Object,从中可以得出结论:所有的数