C# でボックス化とアンボックス化が必要なのはなぜですか?
ボックス化とアンボックス化が何であるかは知っていますが、実際の使用法が理解できません。なぜ、どこで使用すればよいのでしょうか?
short s = 25;
object objshort = s; //Boxing
short anothershort = (short)objshort; //Unboxing
ベストアンサー1
なぜ
統一された型システムを持ち、値型が、参照型が基になるデータを表す方法とはまったく異なる基になるデータの表現を持つことを許可します (たとえば、 はint
32 ビットのバケットであり、参照型とはまったく異なります)。
o
次のように考えてください。型の変数がありますobject
。 そして、 がありint
、それを に入れたいとしますo
。はo
どこかの何かへの参照ですが、 はint
どこかの何かへの参照ではありません (結局のところ、単なる数値です)。 つまり、object
を格納できる新しい を作成しint
、そのオブジェクトへの参照を に割り当てますo
。 このプロセスを「ボックス化」と呼びます。
したがって、統一された型システムを必要としない場合 (つまり、参照型と値型の表現方法が大きく異なり、これら 2 つを「表現」する共通の方法を必要としない場合)、ボックス化は必要ありません。int
基になる値を表現する必要がない場合 (つまり、代わりにint
参照型も必要であり、基になる値への参照を格納するだけの場合)、ボックス化は必要ありません。
どこで使えばいいですか。
たとえば、古いコレクション型はsArrayList
のみを消費しますobject
。つまり、どこかに存在するものへの参照のみを格納します。ボックス化しないと、int
そのようなコレクションに を入れることはできません。しかし、ボックス化すれば可能です。
ジェネリック医薬品の時代では、このようなことは実際には必要なく、この問題について考えずに楽しく過ごすことができます。ただし、注意すべき点がいくつかあります。
これは正しいです:
double e = 2.718281828459045;
int ee = (int)e;
これではありません:
double e = 2.718281828459045;
object o = e; // box
int ee = (int)o; // runtime exception
代わりに、次のようにする必要があります。
double e = 2.718281828459045;
object o = e; // box
int ee = (int)(double)o;
double
まず、 ( (double)o
) を明示的にアンボックス化し、それを にキャストする必要がありますint
。
次の結果は何でしょうか。
double e = 2.718281828459045;
double d = e;
object o1 = d;
object o2 = e;
Console.WriteLine(d == e);
Console.WriteLine(o1 == o2);
次の文に進む前に、少し考えてみましょう。
True
素晴らしい!と答えたなら、False
ちょっと待ってください。それは参照型では参照の等価性をチェックするが、基になる値が等しいかどうかはチェックしないからです==
。これは非常に簡単に犯してしまう間違いです。おそらくもっと微妙な間違いです。
double e = 2.718281828459045;
object o1 = e;
object o2 = e;
Console.WriteLine(o1 == o2);
も印刷されますFalse
!
こう言った方が良いでしょう:
Console.WriteLine(o1.Equals(o2));
すると、ありがたいことに、 が印刷されますTrue
。
最後にもう一つ微妙な点があります:
[struct|class] Point {
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Point p = new Point(1, 1);
object o = p;
p.x = 2;
Console.WriteLine(((Point)o).x);
出力はどうなるでしょうか? それは場合によります!Point
が の場合struct
、出力は です1
が、 がPoint
のclass
場合、出力は です2
! ボックス化変換は、ボックス化される値のコピーを作成し、動作の違いを説明します。