基本も基本、参照型変数代入で半日ハマってしまいました。同じオブジェクトを参照している変数は、どの変数を操作してもすべての変数が影響を受けるはずですが、そうならない!! んなアホな。
よくよく考えれば何でもない話なのですが。
参照型
C#には参照型という種類の型があります。クラスを使って定義した型は参照型になります。
参照型の変数は値そのものは持っておらず「値への参照」を保持しています。変数値を別の変数へ代入する時も、実際には値のコピーは行われず、この「値への参照」がコピーされます。なので、コピー先の変数で変数値を操作したらコピー元の変数も同じように変わります。
これは、C++でポインタや参照を使う場合と同じです。C++と違うのは、これが言語側で勝手に処理されるという点です。
参照型代入の例(1)
参照型の代入
class Program
{
class RefType
{
public int val1 = 0;
public int val2 = 0;
}
static void Main(string[] args)
{
RefType A = new RefType { val1 = 1, val2 = 2 };
RefType B = A;
B.val1 = 111; // Bのval1を変更
B.val2 = 222; // Bのval2を変更
Console.WriteLine($"A=[{A.val1} {A.val2}]");
Console.WriteLine($"B=[{B.val1} {B.val2}]");
}
}
結果
A=[111 222]
B=[111 222]
変数Bを操作して、変数Aも変化しています。普通です。
参照型代入の例(2)
これがハマった原因です。
参照型の代入
class Program
{
class RefType
{
public int val1 = 0;
public int val2 = 0;
}
static void Main(string[] args)
{
RefType A = new RefType { val1 = 1, val2 = 2 };
RefType B = A;
// 新しいオブジェクトCを作って、
RefType C = new RefType { val1 = 111, val2 = 222 };
B = C; // Bのval1とval2を同時に変更
Console.WriteLine($"A=[{A.val1} {A.val2}]");
Console.WriteLine($"B=[{B.val1} {B.val2}]");
}
}
結果
A=[1 2]
B=[111 222]
変数Bをそのクラスオブジェクトの代入で変更したのですが、変数Aは変化しません。
これは、変数Bに変数Cを代入した瞬間に変数Bは変数Aの値の参照をやめて、変数Cの値の参照になるからです。Cを代入した時点で変数AとBはなんの関係もなくなってしまいます。
実際にハマったコード
public void function()
{
private Setting setting = mainWindow.setting;
....
setting = (Setting)xml.Deserialize(sr);
....
}
mainWindowクラスのsettingの参照にxmlファイルを読み込もうとしました。しかし、何故か、どうしてもmainWindowクラスのsettingは変更されませんでした。チャンチャン。