値タイプの梱包と取り外し

5598 ワード

値タイプは、オブジェクトとして管理スタックに割り当てる必要がなく、ゴミ回収されず、ポインタで参照されないため、参照タイプよりも「軽量」なタイプです.
        static void Main()
{
System.Collections.ArrayList list = new System.Collections.ArrayList();
Point p;// Point, 。
for (int i = 0; i < 20; i++)
{
p.x = p.y = i;//
list.Add(p);// , ArrayList 。C# IL ,C# , 。 , Point p Point 。 Point ( ) Add 。Point , 。Point p , ArrayList 。
           Point p1 = (Point)list[0];//    ,   
}
}

List.Add()メソッドにはobjectパラメータが必要であり、Addは管理スタック上のオブジェクトへの参照(またはポインタ)をパラメータとして取得する必要がある.コードに伝達されるのはpであり,値タイプであり,コードを正しく動作させるためにPointは既に1回箱詰めされている.
値タイプのインスタンスを梱包するときに内部で発生すること:
1.管理スタックにメモリを割り当てます.
2.値タイプのフィールドは、新しく割り当てられたヒープメモリにコピーされます.
3.オブジェクトのアドレスを返します.このアドレスはオブジェクトへの参照であり、値タイプは参照タイプです.
箱を分解して起こったこと:
1.梱包されたオブジェクトの各フィールドのアドレスを取得します.
2.フィールドに含まれる値をスタックからスタックベースの値タイプインスタンスにコピーします.
箱を取り外す代価は箱に入れるよりずっと低い.ボックスの取り外しは、オブジェクト内の元の値タイプを含むポインタを取得するプロセスです.実際には、ポインタは、ボックスのインスタンス内のボックスが入っていない部分を指します.したがって、ボックスとは異なり、ボックスの取り外しはメモリにバイトをコピーする必要はありません.ボックスの取り外し操作に続いてフィールドのコピー操作が発生することがあります. 
梱包や解体はアプリケーションの速度やメモリ消費に悪影響を及ぼすため、コンパイラがいつコードを生成して自動的にこれらの操作を行うかに注意し、手動でコードを作成して、自動的にコードを生成しないようにしてみましょう.
        static void Main()
{
Int32 i = 5;
object obj = i;//
Int16 n = (Int16)obj;// , InvalidCastException 。 , 。
Int16 nn = (Int16)(Int32)obj;// , 。
Int32 d = (Int32)obj;//
Console.ReadKey();
}

オブジェクトを解体する場合は、元の未梱包の値タイプにのみ変換できます. 
        static void Main()
{
Int32 i = 5;
object obj = i;//
i = 123;
Console.WriteLine(i + "," + (Int32)obj);// ?WriteLine() String , String ,
// , String 。
// String String Concat。
//String.Concat , , 。
// 3 ,
//public static String Concat(object obj0,object obj1,object obj2)
// i,i , 。
//obj1 String 。obj3 。 。
Console.WriteLine(i.ToString() + "," + obj);// 。i ToString , String,String , Concat ,
Console.ReadKey();
}  

FCLを見ると、多くの方法が異なる値タイプのパラメータに対してリロードされていることがわかります.ほとんどの方法でリロードを行う唯一の目的は、定数タイプの梱包操作回数を減らすことです.
未梱包の値タイプが参照タイプよりも「軽量」であることは、次の2つの理由に帰結します.
1.値タイプはスタックに管理されなくなりました.
2.値タイプスタック上の各オブジェクトに追加メンバーがない:1つのタイプのオブジェクトポインタと同期ブロックインデックス.
値タイプに同期ブロックインデックスがないため、はあ、Systemは使用できません.Threading.モニタタイプの様々な方法では、同期は実現できません.
C#でインタフェースを使用してのみ、梱包された値タイプのフィールドを変更できます.詳細は126ページを参照してください.