値型と参照型とは?
C#には値型と参照型というものがあります。この2つの違いを理解していないと、今後いろいろと遭遇する不具合の解決ができない場合があったり、思ったような動作をしないことがあるのでしっかり理解しておきましょう。
値型とは
値型とは、数値等の確保するべきバイト数が明確な型で、型を宣言したときに、特定のバイト数をメモリ上に確保する型の事を言います。代表的なもので言うと、byte,short,int,long,float,double,enum,bool等です。
値型の一覧はマイクロソフトの公式サイトに載っているのでこちらを参照してください。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/value-types-table
この一覧にあるもの以外は参照型です。構造体が値型であることに注意してください。
値型は、宣言した時点で指定したバイト数が確保されます。Int型であれば、intを宣言した時点で、メモリ上に4バイト確保されます。
参照型
参照型は、型を宣言するだけだと何バイト領域を確保するべきかわからないものが参照型になります。代表的なものでいうと、文字列であるstringとクラスです。これらの型は参照型なので、宣言した段階では、値を保持する場所のアドレスのみが確保されます。
値型と参照型の違い
値型と参照型の決定的な違いは、代入したときに顕著に現れます。
値型の場合はintを宣言して、値を「3」で代入し、その値をさらに別のint変数に代入しても、それぞれのint変数が3を保持するため、その後、一方のint変数の値を「4」に変更したとしても、もう一方のint変数は「3」のままで保たれます。これは値型が、それぞれに4バイトのメモリ領域を確保しているからで、それぞれ別の値として動作します。
int a = 10; int b = 20; a = b; b = 30; MessageBox.Show(a.ToString()); MessageBox.Show(b.ToString());
「a = b;」の部分でaとbは20になり、「b = 30;」を行うとaは20、bは30となります。値型の場合は、特に違和感のない動きをするため、特に注意することはありません。
一方、参照型はアドレスを保持しているだけなので、イコールで結んで代入すると、双方の同じアドレスが入ってしまうため、その後、片方のクラスの値を変更した場合ももう一方の連動して値が変更されたように見えてしまいます。これは、もともと値は1つしかなく、2つのクラス変数が同じアドレスを参照しているのが原因で、連動しているというわけではなく、同じ値を見ているという現象によるものです。このように、参照型を扱うときは、アドレスを保持しているという事を意識してコーディングしないと、別の場所で、連動して値を変更してしまう可能性があります。
Other classA = new Other(); Other classB = new Other(); classA.Value = 10; classB.Value = 20; classA = classB; classB.Value = 30; MessageBox.Show(classA.Value.ToString()); MessageBox.Show(classA.Value.ToString());
この場合、classAとclassBはクラスなので参照型の変数です。
最初はclassAとclassBは別のインスタンスなので別のアドレスを参照しています。しかし、「classA = classB;」の行で、別のインスタンスをイコールで結んでしまいました。この状態で、classAとclassBは同じものになり、同じアドレスを参照するようになります。そのため、「classB.Value = 30;」を行うと、classBの値を変更しているだけのつもりが、classAのValueも30に変更されてしまいます。このように、参照型の動作を理解していない場合は、classAとclassBが連動しているように見えてしまいますが、連動しているのではなく、同じ場所を見ているのが原因です。
注意点
次のようにメソッドの引数として、参照型を投げる場合も注意が必要です。引数の参照型を、メソッド内部で値の変更をした場合も、呼び出し側に影響が出ます。
Other classC = new Other(); classC.Value = 40; OtherMethod(classC); MessageBox.Show(classC.Value.ToString()); private void OtherMethod(Other other) { other.Value = 55; }
この場合は最初40だった値が、メソッドを呼びだし、その中で55に変更されているため、MessageBox.Showの段階では55に変更されています。
記述例
namespace S5.値型と参照型 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int a = 10; int b = 20; MessageBox.Show("a=" + a); MessageBox.Show("b=" + b); a = b; MessageBox.Show("a=" + a); MessageBox.Show("b=" + b); b = 30; MessageBox.Show("a=" + a); MessageBox.Show("b=" + b); } private void button2_Click(object sender, EventArgs e) { Other a = new Other(); Other b = new Other(); a.Value = 10; b.Value = 20; MessageBox.Show("a=" + a.Value); MessageBox.Show("b=" + b.Value); a = b; MessageBox.Show("a=" + a.Value); MessageBox.Show("b=" + b.Value); b.Value = 30; MessageBox.Show("a=" + a.Value); //30 MessageBox.Show("b=" + b.Value); } private void button3_Click(object sender, EventArgs e) { Other a = new Other(); a.Value = 10; MessageBox.Show("a=" + a.Value); OtherMethod(a); MessageBox.Show("a=" + a.Value); //55 } private void button4_Click(object sender, EventArgs e) { int a = 10; MessageBox.Show("a=" + a); OtherMethod2(a); MessageBox.Show("a=" + a); //10 } private void OtherMethod(Other other) { other.Value = 55; } private void OtherMethod2(int other) { other = 55; } public class Other { public int Value; } } }
- C#初心者のための基礎!C#文法2割の知識で8割の仕事をする方法!#1
- C#初心者のための基礎!ブロックと名前空間とクラスとメソッドを解説#2
- C#初心者のための基礎!#3値の扱い方。変数と定数をわかりやすく解説!
- C#初心者のための基礎!データ型の種類と使い分けをわかりやすく解説#4
- C#初心者のための基礎!値型と参照型の違いと使い方をわかりやすく解説#5
- C#初心者のための基礎!データ型の変換のやり方をわかりやすく解説#6
- C#初心者のための基礎!配列の使い方をわかりやすく解説#7
- C#初心者のための基礎!動的配列List<T>の使い方をわかりやすく解説#8
- C#初心者のための基礎!演算子の使い方をわかりやすく解説#9
- C#初心者のための基礎!if文とswich文の使い方をわかりやすく解説#10
- C#初心者のための基礎!while文の書き方と使い方をわかりやすく解説#11
- C#初心者のための基礎!do-While文の書き方と使い方をわかりやすく解説#12
- C#初心者のための基礎!for文の書き方と使い方をわかりやすく解説#13
- C#初心者のための基礎!foreach文の書き方と使い方をわかりやすく解説#14
- C#初心者のための基礎!オブジェクト指向の意味をわかりやすく解説#15
- C#初心者のための基礎!クラスの意味と使い方をわかりやすく解説#16
- C#初心者のための基礎!コンストラクタの意味と使い方をわかりやすく解説#17
- C#初心者のための基礎!アクセス修飾子の意味と使い方をわかりやすく解説#18
- C#初心者のための基礎!メソッドの意味と使い方をわかりやすく解説#19
- C#初心者のための基礎!フィールドの意味と使い方をわかりやすく解説#20
- C#初心者のための基礎!インスタンスの意味と使い方をわかりやすく解説#21
- C#初心者のための基礎!カプセル化の意味と使い方をわかりやすく解説#22
- C#初心者のための基礎!プロパティの意味と使い方をわかりやすく解説#23
- C#初心者のための基礎!Disposeとusingの意味と使い方を解説#24
- C#初心者のための基礎!staticスタティックの意味と使い方を解説#25
- C#初心者のための基礎!継承の意味と使い方をわかりやすく解説#26
- C#初心者のための基礎!override(オーバーライド)の使い方を解説#27
- C#初心者のための基礎!ポリモーフィズムとインタフェースの使い方を解説#28
- C#初心者のための基礎!ポリモーフィズムと抽象クラスの使い方を解説#29
- C#初心者のための基礎!例外Exceptionの意味と使い方をわかりやすく解説#30