前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《CLR via C#》Part2之Chapter5 基元类型、引用类型和值类型(二)

《CLR via C#》Part2之Chapter5 基元类型、引用类型和值类型(二)

作者头像
Isaac Zhang
发布2019-09-10 18:10:34
3120
发布2019-09-10 18:10:34
举报
文章被收录于专栏:奔跑的人生

引用类型和值类型

使用引用类型时,必须注意到一些性能损耗,要考虑以下事实:

  1. 内存必须从托管堆上分配
  2. 堆上分配的每个对象都有一些额外的成员,这些成员必须初始化
  3. 对象中的其他字节(为字段而设)总是设置为0
  4. 从托管堆上分配一个对象时,总是强制执行一次垃圾收集操作

虽然FCL得大多数类型都是引用类型,但程序员使用最多的还是值类型,如果一个程序全部使用的是引用类型,那么它的性能会极度低下。

为了提升性能,CLR提供了名为“值类型”的轻量级类型。

值类型不受GC得控制。


.NET Framework SDK明确指出,哪些类型是值类型 OR 引用类型:

任何称为“类”的都是引用类型:System.Exception类、System.Random类;

结构或者枚举为值类型:System.Int32结构、System.Boolean结构、System.DayOfWeek枚举等。

image
image

以下代码演示了引用类型和值类型区别:

代码语言:javascript
复制
//引用类型(类)
代码语言:javascript
复制
class IsaacRef{public Int32 x;}
代码语言:javascript
复制
//值类型(结构)
代码语言:javascript
复制
struct IsaVal{public Int32 x;}
代码语言:javascript
复制
代码语言:javascript
复制
static void ValueTypeDemo(){
代码语言:javascript
复制
     IsaacRef r1 = new IsaacRef();    //在堆上分配
代码语言:javascript
复制
      IsaVal v1 = new IsaVal();        //在栈上分配
代码语言:javascript
复制
      r1.x = 5;//提取指针
代码语言:javascript
复制
      v1.x = 5;//在栈上修改
代码语言:javascript
复制
      Console.WriteLine(r1.x);//显示5
代码语言:javascript
复制
     Console.WriteLine(v1.x);//显示5
代码语言:javascript
复制
代码语言:javascript
复制
     IsaacRef r2 = r1;//只复制引用(指针)
代码语言:javascript
复制
      IsaVal v2 = v1;//在栈上分配并复制成员
代码语言:javascript
复制
      r1.x = 8;//r1.x和r2.x都会改
代码语言:javascript
复制
      v1.x = 9;//v1.x会改,v2.x不会变
代码语言:javascript
复制
      Console.WriteLine(r1.x);//显示8
代码语言:javascript
复制
     Console.WriteLine(r2.x);//显示8
代码语言:javascript
复制
      Console.WriteLine(v1.x);//显示9
代码语言:javascript
复制
     Console.WriteLine(v2.x);//显示5
代码语言:javascript
复制
}

<!-- .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } -->

SNAGHTML6d788b
SNAGHTML6d788b

选择使用值类型还是引用类型

某些时候,值类型能提供更好的性能,具体说除非以下所有条件都满足,否则不应将一个类型声明为值类型:

  1. 类型具有基元类型的行为。(即其中没有成员会修改类型的任何实例字段)
  2. 类型不需要从其他任何类型继承
  3. 类型也不会派生出其他类型

除了满足以上3个条件之外,还必须满足以下任一条件:

  1. 类型的实例较小(约16字节或者更小)
  2. 类型的实例较大(大于16字节),但不作为方法实参传递,也不从方法返回
image
image
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-03-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引用类型和值类型
  • 选择使用值类型还是引用类型
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档