分析.NETインタビューの質問(02) - 梱包および開梱

記事からの転載:http://www.pythonheidong.com/blog/article/2973/

それは、ボクシングや強制でアンボクシングほぼすべての顔の質問の一つであるシンプルに見えますが、しばしば無視する方が簡単です。実際には、それは単純ではない、簡単な質問には、多くのレベルで解釈することができます。

  一般的な面接の質問:

1.開梱と梱包とは何ですか?

2.ボックスとは何ですか?

3.ボックスの?

4.ボクシングとアンボクシングの性能の影響は何ですか?

5.どのようにステルスボクシングを避けるために?

6.ボックスの基本的な構造?

7.パッキングプロセス?

8.開梱プロセス?

9.次のコード出力とは何ですか?どのように多くの時間が梱包されましたか?開梱何回?

int型私= 5 ;
オブジェクト 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から継承された見つけることは難しいことではありませんから来ています。だから、.NETは万物の源であるオブジェクトボクシングとアンボクシングの基礎である、彼女からのほぼすべての種類、。

特に注目すべきなのは、この記事と前回の記事は直接関連している、あなたは用紙の種類と原則の参照型の値を理解する必要があり、私たちはより良い、この記事の内容を理解することができます。

スマイル 基本コンセプト

梱包や開梱すると、参照型と変換の値の型である、彼女は基本的な前提、値型と参照型の間のブリッジであることを特徴とする、彼らは上記の相互に変換することができるということである:オブジェクトは、.NET万物の源であります

小さなサンプルコードを見てみましょう:

            int型 X = 1023 ;
             オブジェクト O = X; // 梱包
            int型 Y =(int型)O; // アンボクシング

パッキング:参照オブジェクトに値型は、インターフェース実装または値型のSystem.Object参照タイプが一般的です。

開梱:基準値の型は、メモを入力するために、ここでの参照は、タイプのみ参照型のオブジェクトを箱詰めされています。

メモリ実行の観点から異なる参照型と値型メモリアロケーションので、パッキング及びアンパッキングはボックス化とアンボックス化のルートであるが、パフォーマンスに影響する、データメモリの割り当てと動作の他のコピーの存在に結合されます

笑い パッキングプロセス

int型 X = 1023 ;
 オブジェクト O = X; // 梱包

ボックス化値型は、特定のプロセスを参照型を変換することです。

  • 1.スタックメモリのアプリケーションは、値型のサイズのメモリサイズ、プラス追加のスペースが固定されている(参照標準タイプ:TypeHandle指標とシンクブロック)。
  • 2.タイプフィールド値の値(X = 1023)新たに割り当てられたメモリのコピー。
  • 新たな基準オブジェクトの前記リターンアドレス(のための参照変数オブジェクト O)

画像

パッキングは、2つのメモリ・オブジェクトを有した後、上記のように:aが値型変数xであり、他方は、新たな基準物体Oです。パッキング対応IL命令box下ILコード上にパッキング:

画像

笑い ボックス化解除プロセス

int型 X = 1023 ;
 オブジェクト O = X; // 梱包
int型 Y =(int型)O; // アンボクシング

私は開梱ボックスは、プロセスは、単に、それはボックス化値型の参照型を変換することで、あるリバース、梱包理解しています。特定のプロセス:

  • 1.無効な検出と同じであるタイプ(INT)のボックス化とアンボックス化の種類、などヌルか、有効なインスタンス・オブジェクト(オブジェクトo)を確認し、例外がスローされます。
  • 2.戻りポインタは、オブジェクトは、アドレス・タイプ・フィールドの値のパッキング(オブジェクトo)値を得ることです。
  • 3.コピーフィールド、ボクシングオブジェクト(オブジェクトo)値がアンパックの値を格納するための新しい値型変数を作成することを意味し、スタック上のタイプフィールドにコピーされます。

画像

開梱後、上記のように、ILアンパック命令に対応する、新しい値型変数yを与えるためにunbox次のように、ILアンボクシングのコードです。

画像 

舌の笑顔 ボクシングとアンボクシングとパフォーマンスの概要

何でいっぱい?何取り壊されますか?ボックスとは何ですか?

ボックス化とアンボックス化の原理の上記深さの理解を介して、理解しやすい、値型のみボックス化することができ、解体は、梱包後のオブジェクトへの参照である、収納ボックスは、ボックスに格納され、オブジェクト・インスタンスの値型フィールドへの参照でありますマネージヒープ。唯一の値の型は、2つの状態を開梱、梱包しており、参照型はボックスにされています

パフォーマンスについて

之所以关注装箱与拆箱,主要原因就是他们的性能问题,而且在日常编码中,经常有装箱与拆箱的操作,而且这些装箱与拆箱的操作往往是在不经意时发生。一般来说,装箱的性能开销更大,这不难理解,因为引用对象的分配更加复杂,成本也更高,值类型分配在栈上,分配和释放的效率都很高。装箱过程是需要创建一个新的引用类型对象实例,拆箱过程需要创建一个值类型字段,开销更低。

为了尽量避免这种性能损失,尽量使用泛型,在代码编写中也尽量避免隐式装箱。

什么是隐式装箱?如何避免?

就是不经意的代码导致多次重复的装箱操作,看看代码就好理解了

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

 

版权所有,文章来源:http://www.cnblogs.com/anding

个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。

.NETインタビューの質問の解決(00) - 記事&インタビューインデックスシリーズについて話を始めます

  参考文献:

ブックス:CLRのC#を経由して

ブック:あなたが知っている必要があります.NET

1.4.2ボクシングとアンボクシング:http://book.51cto.com/art/201012/237726.htm

記事からの転載:http://www.pythonheidong.com/blog/article/2973/

おすすめ

転載: www.cnblogs.com/xiongbatianxiaskjdskjdksjdskdtuti/p/11356786.html