C#におけるオブジェクト参照とメモリ管理の可視化

このスクリーンショットは、C#コードのメモリグラフを視覚化するツールを使って、Playerオブジェクトのメモリの状態を示しています。以下に、各部分の説明と分析を示します。

ツールを使った解析

Player player1 = new Player();
ChangeObj(player1);

Inspect.MemoryGraph(player1);
Inspect.Stack(player1);
Inspect.Heap(player1);

void ChangeObj(Player player)
{
    player = new Player();
    Inspect.MemoryGraph(player);
    Inspect.Stack(player);
    Inspect.Heap(player);
}

class Player
{
}

解説

  1. Player player1 = new Player();
    • player1変数が新しいPlayerオブジェクトを指すように初期化されています。
  2. ChangeObj(player1);
    • player1を引数としてChangeObjメソッドが呼び出されます。ここで、playerplayer1のコピーです。
  3. Inspect.MemoryGraph(player1);Inspect.Stack(player1);Inspect.Heap(player1);
    • player1のメモリ状態を表示しています。この時点でのメモリグラフとスタック、ヒープの状態が右側に表示されています。
  4. void ChangeObj(Player player)
    • player変数に新しいPlayerオブジェクトを割り当てています。この操作はメソッド内でのみ有効で、player1には影響しません。
  5. Inspect.MemoryGraph(player);Inspect.Stack(player);Inspect.Heap(player);
    • ChangeObjメソッド内で新しく割り当てられたplayerのメモリ状態を表示しています。

メモリの状態

右側の結果表示部分には、player1playerのメモリ状態が示されています。以下にそれぞれの説明をします。

  • player1
    • スタックにはplayer1の参照があり、それがヒープ上のPlayerオブジェクトを指しています。
    • ヒープには、0x179814AF7B8アドレスにPlayerオブジェクトが存在します。
  • ChangeObjメソッド内のplayer
    • ChangeObjメソッド内で新しいPlayerオブジェクトが割り当てられています。
    • playerは新しい0x179814AF7A0アドレスのPlayerオブジェクトを指しています。

結論

ChangeObjメソッドは、引数として渡されたplayer1の参照を受け取りますが、メソッド内で新しいPlayerオブジェクトを作成しても、元のplayer1には影響しません。これが、メソッドの外でplayer1が最初に作成されたPlayerオブジェクトを指し続けている理由です。

このメモリの可視化は、参照型の変数がどのように動作するかを理解するのに非常に有用です。特に、メソッド内で新しいオブジェクトを割り当てても、元の参照は変更されないという点が重要です。

C#

Posted by hidepon