バッテラのハローワールド研究室

エンジニア、プログラミングに関する情報を掲載中!

【C#】C#の値渡し・参照渡しを深堀っていく

はじめに

C#の言語仕様で少し気になる部分をまとめようかなと思います。

不定期に更新していきます。

前置き

C#という言語は 構造体は値渡しクラスは参照渡しとうい仕様になっています。

値渡し、参照渡しを説明しだすと長文になるので割愛しますが、

値渡しはクローン、参照渡しはオリジナルと思っていただければOKです

環境

UnityのC#でやってます

クラス型変数を持つ構造体をコピー(代入)した場合

サンプルプログラム

言葉で説明が難しいのでプログラムを作ってみます。

まずクラスとそのクラスの変数をもつ構造体を用意します

public class HogeClass
{
    public int classValue = 0;
}

public struct HogeStruct
{
    public HogeClass hoge; // HogeClassのクラス型変数
    public int structValue; // プリミティブ型変数

}

次に以下のようなことをしていきます

① 構造体aを作り、変数の値をセットします
② 構造体bをaを代入して作ります
③ 構造体bの値をaと違う値でセットします
④ 値を確認します

void Start()
{
    HogeStruct a = new HogeStruct();
    // ①
    a.structValue = 1;
    a.hoge = new HogeClass();
    a.hoge.classValue = 1;

    // ②
    HogeStruct b = a;

    // ③
    b.structValue = 2;
    b.hoge.classValue = 2;

    // ④
    Debug.Log($"a structValue={a.structValue}");
    Debug.Log($"a classValue={a.hoge.classValue}");

    Debug.Log($"b structValue={b.structValue}");
    Debug.Log($"b classValue={b.hoge.classValue}");
}
結果
a structValue=1
a classValue=2
b structValue=2
b classValue=2

まずstructValueに注目しましょう

構造体が持つ変数(strucValue)はそれぞれ異なる値となっています

構造体は値渡しだからここは想像通りですよね。

次にclassValueに注目します

classValueはbでセットした値がaにも反映されています。

つまり aのclassValue と bのclassValue は値を共有していますね。

考察

構造体をコピーしてもクラス型変数はコピーではなく参照になるということ

それぞれの構造体は別々のインスタンスだけど、クラス変数はインスタンスは同じ?。

それとも、

C言語でいうアドレスの値を持つ変数を値渡しでコピーされた認識なのか。

アドレスを持つ変数は別々のインスタンスだけど指し示す先は同じだから値が共有される。

こっちのが方が値渡しという点でしっくりくるかな。

まぁこんなケースはそもそも少ないと思うけど(笑)