型
概要
型には値型と参照型の2種類があります。
値型
データの値そのものを保持する型を値型といいます。
構造体・列挙型が該当します。
構造体(struct)
structキーワードを付与して定義されたものは構造体となり、値型として扱われます。
public struct Hoge { public int Value; }
列挙型(enum)
enumキーワード付与して定義されたものは列挙型となり、値型として扱われます。
public enum Hoge { Value, }
値型の動作
値型は値そのものなので、nullになりません。
変数などで宣言した時点で初期値を持ちます。
内包する要素も各々の型のデフォルト値で初期化されます。
以下コードでは「0」が出力されます。
Hoge hoge; Console.WriteLine(hoge.Value);
また、他の変数・プロパティなどに代入した時点で、それぞれ別物として扱われます。
以下のコードでは各変数のValueはそれぞれ異なる値になります。
Hoge hoge1 = new Hoge(); Hoge hoge2 = hoge1; Hoge hoge3 = hoge2; hoge1.Value = 1; hoge2.Value = 2; hoge3.Value = 3;
値型はスタックメモリ上で管理されます。
ただし、値のスコープがメソッド内など明確に限定されるケースのみで、
クラスメンバ・クロージャなどの場合はヒープメモリ上で管理されます。
参照型
データへの参照を保持する型を参照型といいます。
クラスなどが該当します。
クラス(class)
classキーワードを付与して定義されたものはクラスとなり、参照型として扱われます。
public class Hoge { public int Value; }
参照型の動作
参照型は参照を保持するため、宣言しただけでは何の参照も保持しておらず、nullになります。
Hoge hoge; // 未初期化変数へのアクセスでコンパイルエラーになる Console.WriteLine(hoge.Value);
また、他の変数・プロパティに代入しても全て同じインスタンスを参照します。
以下のコードでは各変数のValueは全て3になります。
Hoge hoge1 = new Hoge(); Hoge hoge2 = hoge1; Hoge hoge3 = hoge2; hoge1.Value = 1; hoge2.Value = 2; hoge3.Value = 3;
参照型はヒープメモリ上で管理されます。
スタック・ヒープ
かなりざっくりした解釈ですが、まとめておきます。
スタック
- 先入れ後出しで情報を管理するメモリ領域
- 高速だが、領域サイズに制限があるため、大きいデータを扱うには不向き
- 先入れ後出しのため、メモリ開放順序がランダムになるようケースでは使えない
→クラスメンバ・クロージャが扱えないのはこのため
ヒープ
- 任意の順序で情報を管理するメモリ領域
- 低速だが、領域サイズを大きく取れるため、大きいデータを扱える
- 先入れ先出しのような制約がないため、メモリ開放順序がランダムになるケースで使える