演習 - 参照型を検出する
- 8 分
参照型には、配列、クラス、および文字列が含まれます。 参照型は、アプリケーションの実行時に値が格納される方法に関して、値の型とは異なる方法で処理されます。
この演習では、参照型と値の型との違いについて学習するほか、new 演算子を使用して、コンピューターのメモリ内の値に変数を関連付ける方法についても学習します。
参照型と値の型との違い
値の型の変数では、その値は "スタック" というストレージの領域に直接格納されます。 スタックとは、CPU で現在実行されているコードに割り当てられているメモリです (スタック フレームまたはアクティブ化フレームとも呼ばれます)。 スタック フレームで実行が完了すると、スタック内の値は削除されます。
参照型の変数では、その値は "ヒープ" と呼ばれる個別のメモリ領域に格納されます。 ヒープとは、オペレーティング システム上で同時に実行されている多数のアプリケーション間で共有されるメモリ領域です。 .NET ランタイムでは、オペレーティング システムと通信して、使用可能なメモリ アドレスを特定し、値を格納できるアドレスを要求します。 .NET ランタイムでは、値を格納してから、メモリ アドレスをその変数に返します。 ご利用のコードでこの変数が使用される場合、.NET ランタイムによって、変数に格納されたアドレスがシームレスに検索され、そこに格納されている値が取得されます。
次に、これらのアイデアをより明確に示すコードを作成します。
参照型の変数を定義する
前の演習のコードをすべて削除するか、行コメント演算子
//を使ってコメントアウトしてください。Visual Studio Code エディターで次のようにコードを更新してください。
int[] data;前のコードでは、
int型の配列の値を保持できる変数が定義されています。この時点で、
dataは、参照 (もっと厳密には値のメモリ アドレス) をヒープ内に格納することが可能な単なる変数です。 これはメモリ アドレスを指していないため、"null 参照" と呼ばれます。intキーワードを使用してnew配列のインスタンスを作成します次のコードを使用して、Visual Studio Code Editor でコードを更新し、
int配列の新しいインスタンスを作成して割り当てます。int[] data; data = new int[3];newキーワードは、.NET ランタイムにint配列のインスタンスを作成してから、配列のサイズが 3 の int 値をメモリに格納するためにオペレーティング システムと調整するように指示します。 .NET ランタイムは、新しいint配列のメモリ アドレスをコンパイルして返します。 最後に、メモリ アドレスは変数データに格納されます。int配列の要素の既定は、0の既定値である値intです。1 行のコードで、両方の操作を実行できるようにコードの例を変更します
通常は、前の手順の 2 行から成るコードを 1 行のコードに短縮して、変数の宣言と、
int配列の新しいインスタンスの作成の両方が行われます。 ステップ 3 のコードを、次のように変更します。int[] data = new int[3];出力はありませんが、この演習により、参照型を操作するプロセスの手順に C# 構文がどのように関連しているかを明確にできました。
C# 文字列データ型の違い
string データ型も参照型です。 文字列を宣言するときに、なぜ new 演算子を使用しないのか疑問に思われるかもしれません。 これは純粋に、C# の設計者によってもたらされた利便性です。
string データ型は非常に頻繁に使用されるため、次の形式を使用できます。
string shortenedString = "Hello World!";
Console.WriteLine(shortenedString);
しかし、背後では、System.String の新しいインスタンスが作成され、"Hello World!" に初期化されます。
値および参照の型の使用に関する実用的な懸念事項
-
値の型 (int):次の例では、
val_Aとval_Bが整数値型です。
int val_A = 2;
int val_B = val_A;
val_B = 5;
Console.WriteLine("--Value Types--");
Console.WriteLine($"val_A: {val_A}");
Console.WriteLine($"val_B: {val_B}");
次の出力が表示されます。
--Value Types--
val_A: 2
val_B: 5
val_B = val_A を実行すると、val_A の値がコピーされ、val_B に格納されます。 そのため、val_B が変更されても、val_A は影響を受けません。
-
参照の型 (array):この例では、
ref_Aとref_Bが配列参照型です。
int[] ref_A= new int[1];
ref_A[0] = 2;
int[] ref_B = ref_A;
ref_B[0] = 5;
Console.WriteLine("--Reference Types--");
Console.WriteLine($"ref_A[0]: {ref_A[0]}");
Console.WriteLine($"ref_B[0]: {ref_B[0]}");
次の出力が表示されます。
--Reference Types--
ref_A[0]: 5
ref_B[0]: 5
ref_B = ref_A を実行すると、ref_B は、ref_A と同じメモリ位置を指します。 したがって、両方とも同じメモリ位置を指すため、ref_B[0] が変更されると、ref_A[0] も変更されます。 これは、値の型と参照の型の主要な違いです。
まとめ
- 値の型ではより小さい値を保持することができます。値の型はスタックに格納されます。 参照型では大きな値を保持できます。参照型の新しいインスタンスは、
new演算子を使用して作成されます。 参照型の変数では、ヒープに格納されている実際の値への参照 (メモリ アドレス) が保持されます。 - 参照型には、配列、文字列、およびクラスが含まれます。
自分の知識をチェックする
フィードバック
このページはお役に立ちましたか?
いいえ
このトピックについてサポートが必要ですか?
このトピックの意図を把握したり、理解を深めたりするために Ask Learn を使ってみませんか?