C#のget/setとは?プロパティの使い方・意味・書き方を初心者向けに解説
はじめに
C#を学び始めると、クラスの中でよく見かけるのがgetやsetです。
C#public string Name { get; set; }
このような書き方を見て、「これは変数なのか」「getとsetは何をしているのか」「なぜpublic string name;ではだめなのか」と疑問に思う初心者は多いです。
C#のgetとsetは、クラスの値を外部から読み取ったり、書き込んだりするための仕組みです。特にC#では、クラスのデータを扱うときに「プロパティ」という機能をよく使います。
この記事では、C#のget/setとは何か、プロパティの意味、基本的な書き方、自動実装プロパティ、値のチェック方法、よくあるエラーまで、初心者向けにわかりやすく解説します。
1. C#のget/setとは?まず結論から初心者向けに解説
1-1. get/setは「プロパティ」で値を取得・設定するための仕組み
C#のgetとsetは、プロパティで使われるキーワードです。
プロパティとは、クラスの外部から値を読み書きするための仕組みです。
たとえば、次のコードを見てください。
C#public class Person
{
public string Name { get; set; }
}
このNameがプロパティです。
getは値を取得するための処理、setは値を設定するための処理を表しています。
C#Person person = new Person();
person.Name = "Taro"; // setが使われる
Console.WriteLine(person.Name); // getが使われる
このように、見た目は普通の変数のように扱えますが、内部ではgetとsetが動いています。
1-2. getは値を読み取る処理、setは値を書き込む処理
getは、プロパティの値を読み取るときに呼ばれます。
C#Console.WriteLine(person.Name);
このようにperson.Nameの値を使うとき、getが動きます。
一方、setはプロパティに値を代入するときに呼ばれます。
C#person.Name = "Hanako";
このようにperson.Nameへ値を入れるとき、setが動きます。
つまり、C#のget/setは次のように考えるとわかりやすいです。
C#get → 値を読む
set → 値を書き込む
1-3. { get; set; } は自動実装プロパティの省略記法
C#では、次のような書き方をよく使います。
C#public string Name { get; set; }
これは「自動実装プロパティ」と呼ばれます。
自動実装プロパティは、値を保存するための内部的なフィールドをC#が自動で用意してくれる書き方です。
本来であれば、次のようにフィールドを用意して、getとsetの中で値を扱います。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
しかし、単純に値を読み書きするだけなら、次のように短く書けます。
C#public string Name { get; set; }
初心者のうちは、まずこの{ get; set; }の形を覚えるとよいでしょう。
1-4. get/setを使うと何が便利なのか
get/setを使うと、クラスの値を安全に扱えるようになります。
たとえば、年齢を表すAgeにマイナスの値が入ると困ります。
C#person.Age = -10;
年齢が-10というのは不自然です。
このような場合、setの中にチェック処理を書くことで、不正な値を防げます。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
if (value >= 0)
{
age = value;
}
}
}
このように、get/setを使うことで、単に値を読み書きするだけでなく、値のチェックや加工もできます。
2. C#のプロパティとは?フィールドとの違い
2-1. フィールドとはクラスが持つ変数のこと
フィールドとは、クラスの中に定義する変数のことです。
C#public class Person
{
private string name;
}
このnameがフィールドです。
フィールドは、クラスが内部でデータを保持するために使います。
たとえば、名前、年齢、住所、点数など、オブジェクトが持つ情報を保存する場所として使われます。
C#public class Student
{
private string name;
private int score;
}
この例では、nameとscoreがフィールドです。
2-2. プロパティとは外部から安全に値を扱うための窓口
プロパティは、クラスの外部から値を読み書きするための窓口です。
C#public class Person
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
この例では、nameというフィールドを直接外部に公開せず、Nameというプロパティを通して値を扱っています。
外部からは次のように使えます。
C#Person person = new Person();
person.Name = "Taro";
Console.WriteLine(person.Name);
Nameは変数のように見えますが、実際にはgetとsetを通してnameフィールドにアクセスしています。
2-3. publicフィールドではなくプロパティを使う理由
C#では、フィールドをそのままpublicにするよりも、プロパティを使うのが一般的です。
たとえば、次のような書き方もできます。
C#public class Person
{
public string name;
}
この場合、外部から自由にnameを書き換えられます。
C#Person person = new Person();
person.name = "Taro";
一見シンプルですが、後から値のチェックや変更制限を入れたいときに困ります。
たとえば、年齢をpublicフィールドにしていると、外部から不正な値を入れられてしまいます。
C#public class Person
{
public int age;
}
C#Person person = new Person();
person.age = -100;
これでは安全ではありません。
プロパティを使えば、外部からの見た目はシンプルなまま、内部でチェック処理を追加できます。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
if (value >= 0)
{
age = value;
}
}
}
2-4. カプセル化とget/setの関係
カプセル化とは、クラスの内部データを外部から直接触れないようにし、必要な操作だけを公開する考え方です。
C#では、フィールドをprivateにして、プロパティをpublicにすることでカプセル化を実現できます。
C#public class Person
{
private int age;
public int Age
{
get
{
return age;
}
set
{
if (value >= 0)
{
age = value;
}
}
}
}
このコードでは、ageフィールドはクラスの外から直接変更できません。
C#person.age = -10; // エラー
しかし、Ageプロパティを通してなら値を設定できます。
C#person.Age = 20;
このとき、setの中で値をチェックできます。
つまり、get/setはカプセル化を実現するための重要な仕組みです。
3. C#のget/setの基本的な書き方
3-1. 基本構文:public 型 プロパティ名 { get; set; }
C#のプロパティは、基本的に次のように書きます。
C#アクセス修飾子 型 プロパティ名 { get; set; }
よく使う形は次の通りです。
C#public string Name { get; set; }
public int Age { get; set; }
public bool IsActive { get; set; }
publicは、クラスの外部からアクセスできることを表します。
stringやintは、プロパティが扱う値の型です。
NameやAgeはプロパティ名です。
{ get; set; }は、値の取得と設定ができることを意味します。
3-2. string型のプロパティを書く例
文字列を扱うプロパティは、string型で書きます。
C#public class Person
{
public string Name { get; set; }
}
使うときは次のように書きます。
C#Person person = new Person();
person.Name = "Taro";
Console.WriteLine(person.Name);
実行結果は次のようになります。
C#Taro
person.Name = "Taro";でsetが動き、Console.WriteLine(person.Name);でgetが動きます。
3-3. int型のプロパティを書く例
整数を扱うプロパティは、int型で書きます。
C#public class Person
{
public int Age { get; set; }
}
使うときは次のように書きます。
C#Person person = new Person();
person.Age = 25;
Console.WriteLine(person.Age);
実行結果は次のようになります。
C#25
Ageはint型なので、整数を代入できます。
C#person.Age = 30;
ただし、文字列は代入できません。
C#person.Age = "30"; // エラー
3-4. プロパティ名は大文字始まりにするのが一般的
C#では、プロパティ名は大文字始まりのPascalCaseで書くのが一般的です。
C#public string Name { get; set; }
public int Age { get; set; }
public string EmailAddress { get; set; }
一方、フィールド名は小文字始まりにすることが多いです。
C#private string name;
private int age;
プロパティとフィールドを組み合わせると、次のようになります。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
このように、nameはフィールド、Nameはプロパティとして区別します。
4. getとsetの動きをコード例で理解する
4-1. getでプロパティの値を取得する
getは、プロパティの値を読み取るときに使われます。
次のコードを見てください。
C#public class Person
{
private string name = "Taro";
public string Name
{
get
{
return name;
}
}
}
このNameプロパティにはgetだけがあります。
使うときは次のように書きます。
C#Person person = new Person();
Console.WriteLine(person.Name);
このとき、getの中の処理が実行され、nameの値が返されます。
C#return name;
つまり、getは「このプロパティを読まれたときに、どの値を返すか」を決める部分です。
4-2. setでプロパティに値を代入する
setは、プロパティに値を代入するときに使われます。
C#public class Person
{
private string name;
public string Name
{
set
{
name = value;
}
}
}
この場合、次のように値を代入できます。
C#Person person = new Person();
person.Name = "Hanako";
このとき、setの中の処理が実行されます。
C#name = value;
valueには、代入された値が入ります。
この例では、"Hanako"がvalueに入り、それがnameフィールドに保存されます。
4-3. set内で使うvalueの意味
setの中では、valueという特別な名前が使えます。
C#public string Name
{
set
{
name = value;
}
}
valueは、プロパティに代入された値を表します。
たとえば、次のように書いた場合を考えます。
C#person.Name = "Taro";
このとき、setの中では次のようなイメージになります。
C#name = "Taro";
つまり、valueは自分で宣言しなくても使える特別な変数のようなものです。
int型のプロパティなら、valueもint型になります。
C#private int age;
public int Age
{
set
{
age = value;
}
}
C#person.Age = 20;
この場合、valueには20が入ります。
4-4. 実行結果からget/setの流れを確認する
getとsetの動きをわかりやすくするために、処理の中でメッセージを表示してみましょう。
C#using System;
public class Person
{
private string name;
public string Name
{
get
{
Console.WriteLine("getが呼ばれました");
return name;
}
set
{
Console.WriteLine("setが呼ばれました");
name = value;
}
}
}
public class Program
{
public static void Main()
{
Person person = new Person();
person.Name = "Taro";
Console.WriteLine(person.Name);
}
}
実行結果は次のようになります。
C#setが呼ばれました
getが呼ばれました
Taro
まず、person.Name = "Taro";でsetが呼ばれます。
次に、Console.WriteLine(person.Name);でgetが呼ばれます。
そして、getが返した"Taro"が表示されます。
このように、プロパティは見た目は変数のように使えますが、内部ではgetとsetの処理が動いています。
5. 自動実装プロパティ { get; set; } の使い方
5-1. 自動実装プロパティとは
自動実装プロパティとは、getとsetの中身を省略して書けるプロパティです。
C#public string Name { get; set; }
これは、次のようなプロパティを短く書いたものと考えるとわかりやすいです。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
単純に値を保存して取り出すだけなら、自動実装プロパティを使うのが便利です。
5-2. バッキングフィールドを書かなくてよい理由
プロパティの値を実際に保存するためのフィールドを、バッキングフィールドと呼びます。
手動で書く場合は、次のようにフィールドを用意します。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
しかし、自動実装プロパティでは、このバッキングフィールドをC#が内部的に用意してくれます。
C#public string Name { get; set; }
そのため、開発者が明示的にprivate string name;を書く必要はありません。
5-3. 自動実装プロパティのメリット
自動実装プロパティには、主に次のようなメリットがあります。
コードが短くなり、読みやすくなります。
C#public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
単純なデータを持つクラスでは、プロパティをたくさん書くことがあります。
毎回バッキングフィールドを書いていると、コードが長くなってしまいます。
C#private string name;
private int age;
private string email;
自動実装プロパティを使えば、必要最小限のコードでプロパティを定義できます。
また、後から処理を追加したくなった場合は、通常のプロパティに書き換えることもできます。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
if (value >= 0)
{
age = value;
}
}
}
最初は自動実装プロパティで書いておき、必要になったらget/setの中に処理を書く、という使い方ができます。
5-4. 初心者がまず覚えるべき書き方
C#初心者がまず覚えるべき書き方は、次の形です。
C#public 型 プロパティ名 { get; set; }
具体例は次の通りです。
C#public string Name { get; set; }
public int Age { get; set; }
public bool IsStudent { get; set; }
クラス全体では次のようになります。
C#public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
この形はC#で非常によく使われます。
まずは「{ get; set; }は、外部から値を読み書きできるプロパティ」と覚えるとよいでしょう。
6. get/setを省略・制限する書き方
6-1. getだけを書く読み取り専用プロパティ
プロパティには、getだけを書くこともできます。
C#public string Name { get; }
この場合、外部から値を読み取ることはできますが、外部から代入することはできません。
C#Console.WriteLine(person.Name); // 読み取りはできる
person.Name = "Taro"; // エラー
読み取り専用にしたい値には、getだけのプロパティを使います。
たとえば、作成後に変更されたくないIDなどに使えます。
C#public class User
{
public int Id { get; }
public User(int id)
{
Id = id;
}
}
この場合、Idはコンストラクターで設定され、その後は外部から変更できません。
6-2. setだけを書く書き込み専用プロパティ
setだけのプロパティも書けます。
C#private string password;
public string Password
{
set
{
password = value;
}
}
この場合、外部から値を設定することはできますが、読み取ることはできません。
C#user.Password = "secret"; // 設定はできる
Console.WriteLine(user.Password); // エラー
ただし、書き込み専用プロパティは初心者が頻繁に使うものではありません。
読み取れないプロパティは使い方がわかりにくくなることもあるため、必要な場面だけで使うのがよいでしょう。
6-3. private setで外部からの変更を禁止する
private setを使うと、外部からの変更を禁止しつつ、クラスの内部からは値を変更できます。
C#public class Person
{
public string Name { get; private set; }
public Person(string name)
{
Name = name;
}
public void ChangeName(string newName)
{
Name = newName;
}
}
この場合、外部から値を読むことはできます。
C#Console.WriteLine(person.Name);
しかし、外部から直接代入することはできません。
C#person.Name = "Taro"; // エラー
一方、クラス内部のメソッドからは変更できます。
C#public void ChangeName(string newName)
{
Name = newName;
}
private setは、値の変更方法をクラス側で管理したいときに便利です。
6-4. 読み取り専用にしたいケースの具体例
読み取り専用にしたいケースとして、ユーザーIDや作成日時などがあります。
C#public class User
{
public int Id { get; }
public DateTime CreatedAt { get; }
public User(int id)
{
Id = id;
CreatedAt = DateTime.Now;
}
}
この例では、IdとCreatedAtは作成時に設定され、その後は外部から変更できません。
C#User user = new User(1);
Console.WriteLine(user.Id);
Console.WriteLine(user.CreatedAt);
一方で、名前やメールアドレスのように後から変更する可能性がある値は、setを用意することがあります。
C#public string Name { get; set; }
public string Email { get; set; }
このように、変更してよい値にはsetを用意し、変更されたくない値にはgetだけやprivate setを使います。
7. get/setに処理を書く方法
7-1. バッキングフィールドを使ったプロパティの書き方
get/setの中に処理を書きたい場合は、バッキングフィールドを用意します。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
このageがバッキングフィールドです。
プロパティAgeは、外部から値を扱うための窓口です。
外部から見ると、次のように使えます。
C#person.Age = 20;
Console.WriteLine(person.Age);
しかし内部では、setでageに値を保存し、getでageの値を返しています。
7-2. setで入力値をチェックする
setの中では、代入された値をチェックできます。
たとえば、年齢にマイナス値を入れたくない場合は、次のように書きます。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
if (value >= 0)
{
age = value;
}
}
}
このコードでは、valueが0以上のときだけageに代入します。
C#person.Age = 20; // OK
person.Age = -5; // 代入されない
このように、setを使うと不正な値が入るのを防げます。
7-3. 不正な値を防ぐバリデーション例
不正な値が入った場合に、例外を投げることもできます。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢にマイナスの値は設定できません。");
}
age = value;
}
}
使う側のコードは次のようになります。
C#Person person = new Person();
person.Age = 25;
person.Age = -1;
-1を設定しようとすると、エラーになります。
文字列のプロパティでもチェックできます。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("名前は空にできません。");
}
name = value;
}
}
このように、setにバリデーションを書くことで、オブジェクトの状態を正しく保てます。
7-4. getで加工した値を返す例
getでは、フィールドの値をそのまま返すだけでなく、加工して返すこともできます。
たとえば、姓と名を組み合わせてフルネームを返すプロパティを作れます。
C#public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get
{
return LastName + " " + FirstName;
}
}
}
使うときは次のようになります。
C#Person person = new Person();
person.LastName = "Yamada";
person.FirstName = "Taro";
Console.WriteLine(person.FullName);
実行結果は次の通りです。
C#Yamada Taro
FullNameは、値を保存しているわけではありません。
getが呼ばれるたびに、LastNameとFirstNameを組み合わせて返しています。
このように、getを使うと計算結果や加工済みの値をプロパティとして見せることができます。
8. C#のget/setでよくある初心者の疑問
8-1. { get; set; } はメソッドなのか
{ get; set; }は、見た目はメソッドのようにも見えますが、プロパティのアクセサーです。
getやsetは、プロパティにアクセスしたときに呼ばれる特別な処理です。
たとえば、次のコードがあります。
C#public string Name { get; set; }
使うときは、メソッドのように呼び出しません。
C#person.Name = "Taro";
Console.WriteLine(person.Name);
次のようには書きません。
C#person.Name();
person.setName("Taro");
C#のプロパティは、変数のような見た目で使えるのが特徴です。
8-2. get/setとgetter/setterメソッドの違い
他の言語では、値を取得するメソッドをgetter、値を設定するメソッドをsetterと呼ぶことがあります。
たとえば、Javaでは次のような書き方をよく使います。
C#GetName()
SetName("Taro")
C#でも、考え方としては似ています。
しかし、C#ではプロパティを使うため、次のように書けます。
C#person.Name = "Taro";
Console.WriteLine(person.Name);
メソッド呼び出しのように書かなくても、プロパティを通してgetとsetが呼ばれます。
つまり、C#のget/setは、getter/setterの考え方をより自然な構文で使える仕組みです。
8-3. プロパティと変数は何が違うのか
プロパティは変数のように見えますが、変数そのものではありません。
C#public string Name { get; set; }
このNameは、値を読み書きするためのプロパティです。
一方、フィールドはクラスの中にある変数です。
C#private string name;
違いを簡単にまとめると、フィールドは値を保存する場所、プロパティは値を安全に扱うための窓口です。
外部からはプロパティを使い、内部ではフィールドに値を保存する、という形がよく使われます。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
ただし、自動実装プロパティでは、内部のフィールドをC#が自動で用意してくれます。
C#public string Name { get; set; }
8-4. なぜJavaのようにgetName/setNameと書かないのか
C#では、プロパティという仕組みがあるため、JavaのようにgetName()やsetName()と書く必要がありません。
たとえば、Java風に考えると次のようになります。
C#person.SetName("Taro");
Console.WriteLine(person.GetName());
C#では、これを次のように書けます。
C#person.Name = "Taro";
Console.WriteLine(person.Name);
この方が、値を扱っていることが直感的にわかります。
また、後からsetにチェック処理を追加しても、使う側のコードは変わりません。
C#person.Name = "Taro";
この書き方のまま、内部でバリデーションや加工処理を行えます。
C#では、クラスのデータを外部に公開するときは、メソッドではなくプロパティを使うのが一般的です。
9. C#のget/setでよくあるエラーと注意点
9-1. setを書かないプロパティに代入してしまう
setがないプロパティには、外部から値を代入できません。
C#public class Person
{
public string Name { get; }
}
この状態で次のように書くとエラーになります。
C#Person person = new Person();
person.Name = "Taro"; // エラー
getだけのプロパティは読み取り専用です。
外部から代入したい場合は、setを追加します。
C#public string Name { get; set; }
ただし、変更されたくない値であれば、getだけにするのは正しい設計です。
9-2. getを書かないプロパティを読み取ろうとする
getがないプロパティは、外部から読み取れません。
C#public class User
{
private string password;
public string Password
{
set
{
password = value;
}
}
}
この場合、次のように値を設定することはできます。
C#user.Password = "secret";
しかし、読み取ることはできません。
C#Console.WriteLine(user.Password); // エラー
getがないプロパティは書き込み専用です。
通常の値として読み書きしたい場合は、getとsetの両方を書きます。
C#public string Password { get; set; }
9-3. プロパティ名とフィールド名を混同する
初心者がよく間違えるのが、プロパティ名とフィールド名の混同です。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
この例では、nameがフィールドで、Nameがプロパティです。
C#では大文字と小文字が区別されます。
C#name
Name
この2つは別のものです。
一般的には、フィールドは小文字始まり、プロパティは大文字始まりにします。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
名前を似せることで対応関係がわかりやすくなりますが、混同しないように注意しましょう。
9-4. get/set内で同じプロパティを呼び出して無限ループになる
getやsetの中で、同じプロパティを使ってしまうと無限ループになることがあります。
悪い例を見てみましょう。
C#public string Name
{
get
{
return Name;
}
set
{
Name = value;
}
}
このコードでは、getの中でNameを返しています。
しかし、Nameを読むとまたgetが呼ばれます。
つまり、getが何度も自分自身を呼び出してしまいます。
setも同じです。
C#set
{
Name = value;
}
Nameに代入すると、またsetが呼ばれます。
正しくは、バッキングフィールドを使います。
C#private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
get/setの中では、プロパティ自身ではなく、対応するフィールドを使うようにしましょう。
10. 実践例:クラスでget/setを使ってみよう
10-1. Personクラスを作成する
ここからは、実際にPersonクラスを作成して、get/setの使い方を確認します。
まずは、名前と年齢を持つPersonクラスを作ります。
C#public class Person
{
}
この中に、NameプロパティとAgeプロパティを追加していきます。
10-2. NameプロパティとAgeプロパティを定義する
まずは、自動実装プロパティを使って書いてみましょう。
C#public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Nameは文字列なのでstring型です。
Ageは整数なのでint型です。
どちらも{ get; set; }があるため、外部から値を読み書きできます。
10-3. Mainメソッドから値を設定・取得する
次に、MainメソッドからPersonクラスを使ってみます。
C#using System;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Program
{
public static void Main()
{
Person person = new Person();
person.Name = "Taro";
person.Age = 25;
Console.WriteLine(person.Name);
Console.WriteLine(person.Age);
}
}
実行結果は次のようになります。
C#Taro
25
person.Name = "Taro";でNameプロパティのsetが使われます。
person.Age = 25;でAgeプロパティのsetが使われます。
その後、Console.WriteLine(person.Name);とConsole.WriteLine(person.Age);で、それぞれのgetが使われます。
10-4. 年齢にマイナス値を入れられないようにする
次に、Ageにマイナス値を入れられないようにしてみましょう。
この場合、自動実装プロパティではなく、バッキングフィールドを使ってsetにチェック処理を書きます。
C#using System;
public class Person
{
private int age;
public string Name { get; set; }
public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢にマイナスの値は設定できません。");
}
age = value;
}
}
}
public class Program
{
public static void Main()
{
Person person = new Person();
person.Name = "Taro";
person.Age = 25;
Console.WriteLine(person.Name);
Console.WriteLine(person.Age);
person.Age = -1;
}
}
このコードでは、Ageに-1を代入しようとすると例外が発生します。
C#throw new ArgumentException("年齢にマイナスの値は設定できません。");
このように、setに処理を書くことで、不正な値が入るのを防げます。
11. C#のget/setを使うべき場面・使わなくてもよい場面
11-1. 外部から値を読み書きしたい場合
クラスの外部から値を読み書きしたい場合は、プロパティを使います。
C#public class Product
{
public string Name { get; set; }
public int Price { get; set; }
}
使う側は次のように書けます。
C#Product product = new Product();
product.Name = "Book";
product.Price = 1200;
Console.WriteLine(product.Name);
Console.WriteLine(product.Price);
このように、外部から自然に値を扱いたい場合は、publicなプロパティを用意するのが一般的です。
11-2. 値の変更を制限したい場合
値を外部から自由に変更されたくない場合も、プロパティが役立ちます。
たとえば、商品のIDを外部から変更されたくない場合は、private setを使えます。
C#public class Product
{
public int Id { get; private set; }
public string Name { get; set; }
public Product(int id)
{
Id = id;
}
}
この場合、Idは外部から読み取れます。
C#Console.WriteLine(product.Id);
しかし、外部から変更することはできません。
C#product.Id = 10; // エラー
このように、値の変更を制限したい場合にget/setは便利です。
11-3. 入力チェックや加工処理を入れたい場合
入力チェックをしたい場合は、setに処理を書きます。
C#private int price;
public int Price
{
get
{
return price;
}
set
{
if (value < 0)
{
throw new ArgumentException("価格にマイナスの値は設定できません。");
}
price = value;
}
}
加工した値を返したい場合は、getに処理を書きます。
C#public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get
{
return LastName + " " + FirstName;
}
}
このように、単なる値の保存だけでなく、チェックや加工が必要な場合にもプロパティを使います。
11-4. クラス内部だけで使う値ならprivateフィールドでよい
すべての値をプロパティにする必要はありません。
クラス内部だけで使う値なら、privateフィールドで十分な場合もあります。
C#public class Counter
{
private int count;
public void Add()
{
count++;
}
public int GetCount()
{
return count;
}
}
この例では、countはクラス内部で管理されている値です。
外部から直接読み書きさせる必要がないなら、privateフィールドのままで問題ありません。
外部に公開する必要がある値はプロパティにし、内部だけで使う値はprivateフィールドにする、という考え方が基本です。
まとめ
C#のget/setは、プロパティで値を取得・設定するための仕組みです。
getは値を読み取るときに使われ、setは値を代入するときに使われます。
C#public string Name { get; set; }
このような{ get; set; }は、自動実装プロパティと呼ばれる書き方です。
単純に値を読み書きしたい場合は、自動実装プロパティを使うとコードを短く書けます。
一方で、値のチェックや加工をしたい場合は、バッキングフィールドを用意してget/setの中に処理を書きます。
C#private int age;
public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢にマイナスの値は設定できません。");
}
age = value;
}
}
C#では、フィールドをそのままpublicにするよりも、プロパティを使うのが一般的です。
プロパティを使うことで、外部からは変数のようにシンプルに扱え、内部では値のチェックや変更制限を行えます。
初心者のうちは、まず次の形をしっかり覚えましょう。
C#public 型 プロパティ名 { get; set; }
そして、必要に応じてgetだけ、private set、バッキングフィールドを使ったプロパティへと理解を広げていくと、C#のクラス設計がよりわかりやすくなります。

