.NET面试题3
1.什么是拆箱和装箱?
2.什么是箱子?
3.箱子放在哪里?
4.装箱和拆箱有什么性能影响?
5.如何避免隐身装箱?
6.箱子的基本结构?
7.装箱的过程?
8.拆箱的过程?
9.下面这段代码输出什么?共发生多少次装箱?多少次拆箱?
int i = 5;
object obj = i;
IFormattable ftt = i;
Console.WriteLine(System.Object.ReferenceEquals(i, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, ftt));
Console.WriteLine(System.Object.ReferenceEquals(ftt, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)ftt));
深入浅出装箱与拆箱
有拆必有装,有装必有拆。
在上一文中我们提到,所有值类型都是继承自System.ValueType,而System.ValueType又是来自何方呢,不难发现System.ValueType继承自System.Object。因此Object是.NET中的万物之源,几乎所有类型都来自她,这是装箱与拆箱的基础。
特别注意的是,本文与上一文有直接关联,需要先了解上一文中值类型与引用类型的原理,才可以更好理解本文的内容。
基本概念
拆箱与装箱就是值类型与引用类型的转换,她是值类型和引用类型之间的桥梁,他们可以相互转换的一个基本前提就是上面所说的:Object是.NET中的万物之源
先看看一个小小的实例代码:
int x = 1023;
object o = x; //装箱
int y = (int) o; //拆箱
装箱:值类型转换为引用对象,一般是转换为System.Object类型或值类型实现的接口引用类型;
拆箱:引用类型转换为值类型,注意,这里的引用类型只能是被装箱的引用类型对象;
由于值类型和引用类型在内存分配的不同,从内存执行角度看,拆箱与装箱就势必存在内存的分配与数据的拷贝等操作,这也是装箱与拆箱性能影响的根源。
装箱的过程
int x = 1023;
object o = x; //装箱
装箱就是把值类型转换为引用类型,具体过程:
- 1.在堆中申请内存,内存大小为值类型的大小,再加上额外固定空间(引用类型的标配:TypeHandle和同步索引块);
- 2.将值类型的字段值(x=1023)拷贝新分配的内存中;
- 3.返回新引用对象的地址(给引用变量object o)
如上图所示,装箱后内存有两个对象:一个是值类型变量x,另一个就是新引用对象o。装箱对应的IL指令为box
,上面装箱的IL代码如下图:
拆箱的过程
int x = 1023;
object o = x; //装箱
int y = (int) o; //拆箱
明白了装箱,拆箱就是装箱相反的过程,简单的说是把装箱后的引用类型转换为值类型。具体过程:
- 1.检查实例对象(object o)是否有效,如是否为null,其装箱的类型与拆箱的类型(int)是否一致,如检测不合法,抛出异常;
- 2.指针返回,就是获取装箱对象(object o)中值类型字段值的地址;
- 3.字段拷贝,把装箱对象(object o)中值类型字段值拷贝到栈上,意思就是创建一个新的值类型变量来存储拆箱后的值;
如上图所示,拆箱后,得到一个新的值类型变量y,拆箱对应的IL指令为unbox
,拆箱的IL代码如下:
装箱与拆箱总结及性能
装的的什么?拆的又是什么?什么是箱子?
通过上面深入了解了装箱与拆箱的原理,不难理解,只有值类型可以装箱,拆的就是装箱后的引用对象,箱子就是一个存放了值类型字段的引用对象实例,箱子存储在托管堆上。只有值类型才有装箱、拆箱两个状态,而引用类型一直都在箱子里。
关于性能
之所以关注装箱与拆箱,主要原因就是他们的性能问题,而且在日常编码中,经常有装箱与拆箱的操作,而且这些装箱与拆箱的操作往往是在不经意时发生。一般来说,装箱的性能开销更大,这不难理解,因为引用对象的分配更加复杂,成本也更高,值类型分配在栈上,分配和释放的效率都很高。装箱过程是需要创建一个新的引用类型对象实例,拆箱过程需要创建一个值类型字段,开销更低。
为了尽量避免这种性能损失,尽量使用泛型,在代码编写中也尽量避免隐式装箱。
什么是隐式装箱?如何避免?
就是不经意的代码导致多次重复的装箱操作,看看代码就好理解了
int x = 100;
ArrayList arr = new ArrayList(3);
arr.Add(x);
arr.Add(x);
arr.Add(x);
这段代码共有多少次装箱呢?看看Add方法的定义:
再看看IL代码,可以准确的得到装箱的次数:
显示装箱可以避免隐式装箱,下面修改后的代码就只有一次装箱了。
int x = 100;
ArrayList arr = new ArrayList(3);
object o = x;
arr.Add(o);
arr.Add(o);
arr.Add(o);
题目答案解析:
1.什么是拆箱和装箱?
装箱就是值类型转换为引用类型,拆箱就是引用类型(被装箱的对象)转换为值类型。
2.什么是箱子?
就是引用类型对象。
3.箱子放在哪里?
托管堆上。
4.装箱和拆箱有什么性能影响?
装箱和拆箱都涉及到内存的分配和对象的创建,有较大的性能影响。
5.如何避免隐身装箱?
编码中,多使用泛型、显示装箱。
6.箱子的基本结构?
上面说了,箱子就是一个引用类型对象,因此她的结构,主要包含两部分:
- 值类型字段值;
- 引用类型的标准配置,引用对象的额外空间:TypeHandle和同步索引块,关于这两个概念在本系列后面的文章会深入探讨。
7.装箱的过程?
- 1.在堆中申请内存,内存大小为值类型的大小,再加上额外固定空间(引用类型的标配:TypeHandle和同步索引块);
- 2.将值类型的字段值(x=1023)拷贝新分配的内存中;
- 3.返回新引用对象的地址(给引用变量object o)
8.拆箱的过程?
- 1.检查实例对象(object o)是否有效,如是否为null,其装箱的类型与拆箱的类型(int)是否一致,如检测不合法,抛出异常;
- 2.指针返回,就是获取装箱对象(object o)中值类型字段值的地址;
- 3.字段拷贝,把装箱对象(object o)中值类型字段值拷贝到栈上,意思就是创建一个新的值类型变量来存储拆箱后的值;
9.下面这段代码输出什么?共发生多少次装箱?多少次拆箱?
int i = 5;
object obj = i;
IFormattable ftt = i;
Console.WriteLine(System.Object.ReferenceEquals(i, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, ftt));
Console.WriteLine(System.Object.ReferenceEquals(ftt, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)ftt));
上面代码输出如下,至于发生多少次装箱多少次拆箱,你猜?
False
False
False
False
False
.NET面试题3的更多相关文章
- .NET面试题系列[8] - 泛型
“可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用.“ - Jon Skeet .NET面试题系列目录 .NET面试题系列[1] - .NET框架基础知识(1) .NET面试题系列[2] ...
- 关于面试题 Array.indexof() 方法的实现及思考
这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...
- 对Thoughtworks的有趣笔试题实践
记得2014年在网上看到Thoughtworks的一道笔试题,当时觉得挺有意思,但是没动手去写.这几天又在网上看到了,于是我抽了一点时间写了下,我把程序运行的结果跟网上的答案对了一下,应该是对的,但是 ...
- 从阿里巴巴笔试题看Java加载顺序
一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...
- JAVA面试题
在这里我将收录我面试过程中遇到的一些好玩的面试题目 第一个面试题:ABC问题,有三个线程,工作的内容分别是打印出"A""B""C",需要做的 ...
- C++常考面试题汇总
c++面试题 一 用简洁的语言描述 c++ 在 c 语言的基础上开发的一种面向对象编程的语言: 应用广泛: 支持多种编程范式,面向对象编程,泛型编程,和过程化编程:广泛应用于系统开发,引擎开发:支持类 ...
- .NET面试题系列[4] - C# 基础知识(2)
2 类型转换 面试出现频率:主要考察装箱和拆箱.对于有笔试题的场合也可能会考一些基本的类型转换是否合法. 重要程度:10/10 CLR最重要的特性之一就是类型安全性.在运行时,CLR总是知道一个对象是 ...
- 我们公司的ASP.NET 笔试题,你觉得难度如何
本套试题共8个题,主要考察C#面向对象基础,SQL和ASP.NET MVC基础知识. 第1-3题会使用到一个枚举类,其定义如下: public enum QuestionType { Text = , ...
- 我设计的ASP.NET笔试题,你会多少呢
本笔试题考查范围包括面向对象基础.HTML.CSS.JS.EF.jQuery.SQL.编码思想.算法等范围. 第1题:接口和抽象类有何区别? 第2题:静态方法和实例方法有何区别? 第3题:什么是多态? ...
- 猫哥网络编程系列:详解 BAT 面试题
从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...
随机推荐
- boostrap 进入条显示百分比
<div class="progress"> <div class="progress-bar progress-bar-success" ...
- loj#6485. LJJ 学二项式定理(单位根反演)
题面 传送门 题解 首先你要知道一个叫做单位根反演的东西 \[{1\over k}\sum_{i=0}^{k-1}\omega^{in}_k=[k|n]\] 直接用等比数列求和就可以证明了 而且在模\ ...
- 洛谷P4074 [WC2013]糖果公园(莫队)
传送门 总算会树形莫队了…… 上次听说树形莫队是给树分块,实在看不懂.然后用括号序列的方法做总算能弄明白了 先说一下什么是括号序列,就是在$dfs$的时候,进入的时候记录一下,出去的时候也记录一下 拿 ...
- 验证码(captcha)的由来
如果您允许用户在您的网站上发表内容,如留下评论和创建用户配置文件,那么您可能会看到,垃圾留言散播者试图利用这些渠道来给他们自己的网站创造流量.在您的网站上出现这类垃圾留言,对任何人来说都不愉快.用户可 ...
- PAT天梯赛L1-020 帅到没朋友
题目链接:点击打开链接 当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友.本题就要求你找出那些帅到没有朋友的人. 输入格式: 输入第一行给出一个正整数N(<=100),是已知朋 ...
- IDEA总是启动不了
时常怎么都打不开这个软件,或者很久很久才打开. 解决办法:在任务管理器将IDEA结束进程,再去打开软件,就可以了.
- spring cloud 超时时间
zuul.host.socket-timeout-millis=60000 #zuul socket连接超时zuul.host.connect-timeout-millis=60000 #zull 请 ...
- 在本地开发环境没问题,但是发布到服务器出现:未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\106f9ae8\cc0e1169\App_global.asax.haz99mum.dll”--“拒绝访问。 ”错误
解决方法: 1,通常的解决方法:原因是由于系统目录下的Temp目录无相应的权限所致,具体操作如下:C:\Windows\temp-->属性-->安全-->编辑-->添加NETW ...
- centos6.4安装过程中无法出现图形化界面
今天在VMware9.0安装centos6.4的时候,前面的步骤都没问题,到跳过媒体检查这一步后,就发现和之前的不一样了,这次安装不是图形界面,导致后面的安装不方便 一开始以为是centos的版本不一 ...
- xampp 在 windows下 配置 fcgi... 和 opcache 等 优化操作
首先 修改 xampp 的 httpd.conf:(底部加入.方便修改) #fast-cgi 模式 LoadModule fcgid_module modules/mod_fcgid.so <I ...