C# Propertiesとは?初心者向けにプロパティの書き方・get/set・使い方をわかりやすく解説

はじめに

C#を学び始めると、クラスの中でよく登場するのが**Properties(プロパティ)**です。

C#
public string Name { get; set; }
public int Age { get; set; }

このような書き方を見て、「これは変数なの?」「getやsetは何をしているの?」「フィールドと何が違うの?」と疑問に思う人は多いです。

C#のプロパティは、クラスが持つデータを外部から安全に読み書きするための重要な仕組みです。見た目は変数のように使えますが、内部では値を取得したり設定したりする処理を持たせることができます。

この記事では、C# Propertiesの基本から、get/setの意味、自動実装プロパティ、private set、init、required、実践的な使い方まで、初心者にもわかりやすく解説します。

1. C#のProperties(プロパティ)とは?

C#のPropertiesとは、クラスや構造体が持つ値を、外部から読み取ったり設定したりするための仕組みです。

たとえば、Personクラスに名前を持たせたい場合、次のようにプロパティを定義できます。

C#
public class Person
{
public string Name { get; set; }
}

このNameがプロパティです。

使う側は、通常の変数のように値を代入したり、取得したりできます。

C#
Person person = new Person();

person.Name = "Taro";
Console.WriteLine(person.Name);

見た目はシンプルですが、プロパティを使うことで、値の管理やチェックをクラスの中にまとめることができます。

1-1. プロパティはフィールドの値を安全に読み書きするための仕組み

クラスの中に値を保存するための変数をフィールドといいます。

C#
private string name;

このフィールドをそのまま外部に公開してしまうと、どこからでも自由に値を変更できてしまいます。

C#
public string name;

これでも動きますが、後から「空文字は入れたくない」「年齢は0以上にしたい」といった制御を加えにくくなります。

そこでプロパティを使います。

C#
private string name;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

このように書くと、外部からはNameというプロパティを通して値を読み書きできます。内部ではnameというフィールドを使って値を保持しています。

プロパティは、フィールドに直接アクセスさせず、必要に応じて取得や設定の処理を挟むための窓口のようなものです。

1-2. フィールド・メソッド・プロパティの違い

C#では、クラスの中にフィールド、メソッド、プロパティを定義できます。それぞれの役割は異なります。

フィールドは、値そのものを保存するための変数です。

C#
private int age;

メソッドは、処理を実行するためのものです。

C#
public void SayHello()
{
Console.WriteLine("Hello");
}

プロパティは、値を取得したり設定したりするための仕組みです。

C#
public int Age { get; set; }

プロパティは、フィールドのように値を扱えますが、必要に応じてメソッドのように処理を書くこともできます。

C#
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value >= 0)
{
age = value;
}
}
}

この例では、Ageに値を設定するとき、0以上の値だけを受け付けています。

1-3. 初心者がつまずきやすい「変数のように見えてメソッドのように動く」の意味

プロパティは、使う側から見ると変数のように見えます。

C#
person.Age = 20;
Console.WriteLine(person.Age);

しかし、内部ではsetgetの処理が呼び出されています。

C#
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}

person.Age = 20;と書いたときは、setアクセサーが動きます。

Console.WriteLine(person.Age);と書いたときは、getアクセサーが動きます。

つまり、プロパティは見た目は変数のように使えますが、実際には値を取得する処理や設定する処理を持てる仕組みです。

1-4. C#でプロパティを使う主なメリット

C#でプロパティを使う主なメリットは、値の管理を安全にできることです。

たとえば、年齢にマイナスの値を入れたくない場合、setの中でチェックできます。

C#
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢は0以上である必要があります。");
}

age = value;
}
}

プロパティを使うことで、外部からは簡単に値を扱える一方で、クラスの内部では値のチェックや加工ができます。

また、最初は単純なプロパティとして作っておき、後から必要になったタイミングで処理を追加できる点も大きなメリットです。

2. C#プロパティの基本構文

2-1. プロパティの基本的な書き方

C#のプロパティは、次のような構文で書きます。

C#
アクセス修飾子  プロパティ名
{
get
{
値を返す処理
}
set
{
値を設定する処理
}
}

具体例は次のとおりです。

C#
private string name;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

public string Nameの部分で、プロパティの名前と型を定義しています。

getは値を取得するときの処理、setは値を設定するときの処理です。

2-2. getアクセサーとは:値を取得する処理

getアクセサーは、プロパティの値を読み取るときに実行される処理です。

C#
private string name;

public string Name
{
get
{
return name;
}
}

この場合、外部からNameを読み取ると、内部のnameフィールドの値が返されます。

C#
Console.WriteLine(person.Name);

このコードでは、Nameプロパティのgetが呼ばれます。

getの中では、必ずプロパティの型に合った値を返す必要があります。string型のプロパティならstringを返し、int型のプロパティならintを返します。

2-3. setアクセサーとは:値を設定する処理

setアクセサーは、プロパティに値を代入するときに実行される処理です。

C#
private string name;

public string Name
{
set
{
name = value;
}
}

この場合、外部から次のように値を代入すると、setが呼ばれます。

C#
person.Name = "Taro";

setの中では、代入された値をvalueという特別なキーワードで受け取れます。

通常は、valueをフィールドに代入します。

C#
set
{
name = value;
}

2-4. valueキーワードの意味と使い方

valueは、setアクセサーの中で使える特別なキーワードです。

プロパティに代入された値が、自動的にvalueに入ります。

C#
private int age;

public int Age
{
set
{
age = value;
}
}

次のように書いた場合、

C#
person.Age = 25;

setの中では、value25になります。

バリデーションにも使えます。

C#
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢は0以上である必要があります。");
}

age = value;
}
}

このように、valueは「プロパティに設定しようとしている値」と考えると理解しやすいです。

2-5. privateフィールドと組み合わせた基本例

プロパティの基本形は、privateフィールドと組み合わせて使う形です。

C#
public class Person
{
private string name;

public string Name
{
get
{
return name;
}
set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("名前は空にできません。");
}

name = value;
}
}
}

使う側は次のように書けます。

C#
Person person = new Person();

person.Name = "Taro";
Console.WriteLine(person.Name);

Nameプロパティを通して値を設定することで、空文字や不正な値を防げます。

3. 自動実装プロパティとは?

3-1. { get; set; }だけで書けるプロパティ

C#では、単純に値を読み書きするだけなら、もっと短く書けます。

C#
public string Name { get; set; }

これを自動実装プロパティといいます。

自動実装プロパティを使うと、privateフィールドを自分で書かなくても、C#が内部的に値を保持する場所を用意してくれます。

次のような長い書き方を、

C#
private string name;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

次のように短く書けます。

C#
public string Name { get; set; }

3-2. 自動実装プロパティのサンプルコード

自動実装プロパティを使ったクラスの例です。

C#
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

使う側は次のように書けます。

C#
Person person = new Person();

person.Name = "Taro";
person.Age = 20;

Console.WriteLine(person.Name);
Console.WriteLine(person.Age);

とてもシンプルなので、初心者はまずこの形から覚えるとよいでしょう。

3-3. 裏側で生成されるバッキングフィールドとは

自動実装プロパティでは、フィールドを書いていないように見えます。

C#
public string Name { get; set; }

しかし、内部的には値を保存するためのフィールドが必要です。

この内部的に用意されるフィールドをバッキングフィールドと呼びます。

通常のプロパティでは、自分でバッキングフィールドを書きます。

C#
private string name;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

自動実装プロパティでは、このようなフィールドをC#が自動で用意します。

そのため、単純に値を保存して読み書きするだけなら、自動実装プロパティで十分です。

3-4. 通常のプロパティと自動実装プロパティの違い

通常のプロパティは、getsetの中に自由に処理を書けます。

C#
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢は0以上である必要があります。");
}

age = value;
}
}

一方、自動実装プロパティは、基本的には単純な読み書きに向いています。

C#
public int Age { get; set; }

つまり、値のチェックや変換などの処理が必要な場合は通常のプロパティを使い、単純に値を保持したいだけなら自動実装プロパティを使うと考えるとよいです。

3-5. 初心者はまず自動実装プロパティから覚えるべき理由

初心者がC#のプロパティを学ぶときは、まず自動実装プロパティから覚えるのがおすすめです。

理由は、実際のC#コードでは次のような書き方が非常によく使われるからです。

C#
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }

最初から複雑なgetsetの処理を理解しようとすると混乱しやすいです。

まずは、「プロパティはクラスの外から値を読み書きするためのもの」「{ get; set; }で読み書きできる」と理解しましょう。

その後で、値のチェックが必要になったときに、通常のプロパティの書き方を覚えるとスムーズです。

4. get/setの使い分けとアクセス制御

4-1. 読み取り専用プロパティ:getのみ

プロパティは、必ずgetsetの両方を書く必要はありません。

値を外部から読み取るだけにしたい場合は、getだけを書きます。

C#
public class Person
{
private string name = "Taro";

public string Name
{
get
{
return name;
}
}
}

自動実装プロパティでも、getだけの形を書けます。

C#
public string Name { get; }

ただし、getだけの自動実装プロパティは、コンストラクターや初期化子で値を設定する使い方が一般的です。

C#
public class Person
{
public string Name { get; }

public Person(string name)
{
Name = name;
}
}

この場合、作成後に外部からNameを変更することはできません。

4-2. 外部から変更させたくない場合: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)
{
if (string.IsNullOrWhiteSpace(newName))
{
throw new ArgumentException("名前は空にできません。");
}

Name = newName;
}
}

この場合、外部から次のように読み取ることはできます。

C#
Console.WriteLine(person.Name);

しかし、外部から直接代入することはできません。

C#
person.Name = "Jiro"; // エラー

値の変更方法をクラス内のメソッドに限定できるため、意図しない変更を防げます。

4-3. 初期化時だけ値を設定するinit

initは、オブジェクトの初期化時だけ値を設定できるアクセサーです。

C#
public class Person
{
public string Name { get; init; }
public int Age { get; init; }
}

使う側は、オブジェクト初期化子で値を設定できます。

C#
Person person = new Person
{
Name = "Taro",
Age = 20
};

しかし、作成後に値を変更することはできません。

C#
person.Name = "Jiro"; // エラー

initは、作成時に値を入れたいけれど、その後は変更されたくない場合に便利です。

4-4. public・privateなどアクセス修飾子との関係

プロパティには、publicprivateなどのアクセス修飾子を付けられます。

C#
public string Name { get; set; }
private int Age { get; set; }

publicは、クラスの外からアクセスできることを意味します。

C#
person.Name = "Taro";

privateは、同じクラスの中からしかアクセスできないことを意味します。

また、プロパティ全体はpublicにして、setだけprivateにすることもできます。

C#
public string Name { get; private set; }

この場合、読み取りは外部から可能ですが、変更はクラス内部からしかできません。

アクセス制御をうまく使うことで、クラスの外から許可する操作と、内部だけで行う操作を明確に分けられます。

4-5. プロパティで不正な値を防ぐバリデーション例

プロパティのsetでは、値のチェックを行えます。

C#
public class Product
{
private int price;

public int Price
{
get
{
return price;
}
set
{
if (value < 0)
{
throw new ArgumentException("価格は0以上である必要があります。");
}

price = value;
}
}
}

このクラスでは、Priceにマイナスの値を設定しようとすると例外が発生します。

C#
Product product = new Product();

product.Price = 1000;
product.Price = -500; // 例外

このように、プロパティを使うと、クラスが不正な状態になることを防ぎやすくなります。

5. C#プロパティの実践的な使い方

5-1. クラスにNameやAgeなどの情報を持たせる例

C#でクラスを作るとき、名前や年齢などの情報はプロパティとして定義することが多いです。

C#
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

使う側は次のように書けます。

C#
Person person = new Person();

person.Name = "Taro";
person.Age = 20;

Console.WriteLine($"{person.Name}さんは{person.Age}歳です。");

プロパティを使うことで、オブジェクトが持つ情報をわかりやすく表現できます。

5-2. set内で入力値をチェックする例

年齢にマイナスの値を入れたくない場合は、setの中でチェックします。

C#
public class Person
{
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢は0以上である必要があります。");
}

age = value;
}
}
}

このようにしておくと、外部から不正な値を入れようとしても防げます。

C#
Person person = new Person();

person.Age = 20;
person.Age = -1; // 例外

プロパティは、値をただ保存するだけでなく、正しい値だけを受け入れるためにも使えます。

5-3. get内で計算結果を返す例

プロパティは、必ずフィールドの値をそのまま返す必要はありません。

getの中で計算した結果を返すこともできます。

C#
public class Rectangle
{
public int Width { get; set; }
public int Height { get; set; }

public int Area
{
get
{
return Width * Height;
}
}
}

使う側は、面積を変数のように取得できます。

C#
Rectangle rectangle = new Rectangle
{
Width = 5,
Height = 3
};

Console.WriteLine(rectangle.Area);

Areaは値を保存しているわけではなく、WidthHeightから計算して返しています。

このようなプロパティを計算プロパティと呼ぶことがあります。

5-4. コンストラクターとプロパティを組み合わせる例

プロパティはコンストラクターと組み合わせて使うことも多いです。

C#
public class Person
{
public string Name { get; }
public int Age { get; }

public Person(string name, int age)
{
Name = name;
Age = age;
}
}

このクラスでは、オブジェクト作成時にNameAgeを設定します。

C#
Person person = new Person("Taro", 20);

Console.WriteLine(person.Name);
Console.WriteLine(person.Age);

getのみのプロパティにすることで、作成後に値を変更できない設計にできます。

5-5. オブジェクト初期化子でプロパティに値を入れる例

C#では、オブジェクト初期化子を使ってプロパティに値を設定できます。

C#
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

使う側は次のように書けます。

C#
Person person = new Person
{
Name = "Taro",
Age = 20
};

この書き方は、複数のプロパティにまとめて値を入れたいときに便利です。

initと組み合わせると、初期化時だけ値を設定できる安全な設計にできます。

C#
public class Person
{
public string Name { get; init; }
public int Age { get; init; }
}
C#
Person person = new Person
{
Name = "Taro",
Age = 20
};

6. フィールドをpublicにせずプロパティを使う理由

6-1. publicフィールドが避けられる理由

C#では、クラスのデータを外部に公開するとき、publicフィールドではなくプロパティを使うのが一般的です。

次のようなpublicフィールドは、外部から自由に変更できてしまいます。

C#
public class Person
{
public int Age;
}

この場合、次のように不正な値も簡単に入れられます。

C#
Person person = new Person();
person.Age = -10;

年齢がマイナスになるのは不自然ですが、publicフィールドではチェック処理を挟めません。

プロパティを使えば、値の設定時にチェックできます。

C#
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢は0以上である必要があります。");
}

age = value;
}
}

6-2. カプセル化とデータ保護の考え方

プロパティを使う理由のひとつに、カプセル化があります。

カプセル化とは、クラスの内部状態を外部から直接触らせず、決められた方法で操作させる考え方です。

フィールドをprivateにして、プロパティを通してアクセスさせることで、データを安全に管理できます。

C#
public class BankAccount
{
private decimal balance;

public decimal Balance
{
get
{
return balance;
}
}

public void Deposit(decimal amount)
{
if (amount <= 0)
{
throw new ArgumentException("入金額は0より大きい必要があります。");
}

balance += amount;
}
}

この例では、Balanceは外部から読み取れますが、直接変更はできません。

残高を増やすには、Depositメソッドを使う必要があります。

6-3. 後から処理を追加しても呼び出し側を変えずに済む

プロパティを使っておくと、後から処理を追加しても、呼び出し側のコードを大きく変えずに済みます。

最初は単純な自動実装プロパティだったとします。

C#
public string Name { get; set; }

後から「空文字を禁止したい」となった場合、通常のプロパティに変更できます。

C#
private string name;

public string Name
{
get
{
return name;
}
set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("名前は空にできません。");
}

name = value;
}
}

呼び出し側は、これまで通り次のように使えます。

C#
person.Name = "Taro";

外部からの使い方を保ったまま、内部の処理を変更できるのがプロパティの便利な点です。

6-4. C#らしいクラス設計におけるプロパティの役割

C#では、オブジェクトが持つ情報をプロパティとして表現するのが自然です。

C#
public class Product
{
public string Name { get; set; }
public int Price { get; set; }
}

このように書くと、クラスがどのような情報を持っているのかがわかりやすくなります。

また、必要に応じてprivate setinit、バリデーションを使うことで、データを安全に扱えます。

プロパティは、C#らしいクラス設計をするうえで欠かせない基本機能です。

7. よく使うプロパティのパターン

7-1. 読み書き可能なプロパティ

最も基本的なプロパティは、読み書き可能なプロパティです。

C#
public string Name { get; set; }

外部から値を設定でき、読み取ることもできます。

C#
person.Name = "Taro";
Console.WriteLine(person.Name);

単純なデータを扱うクラスでよく使われます。

7-2. 読み取り専用プロパティ

読み取り専用プロパティは、外部から値を取得できますが、変更はできません。

C#
public string Name { get; }

コンストラクターで値を設定する例です。

C#
public class Person
{
public string Name { get; }

public Person(string name)
{
Name = name;
}
}

作成後に変更されたくない値に向いています。

7-3. private set付きプロパティ

private setを使うと、外部からは読み取りのみ可能で、変更はクラス内部だけに制限できます。

C#
public int Count { get; private set; }

たとえば、カウントをメソッド経由で増やす場合に便利です。

C#
public class Counter
{
public int Count { get; private set; }

public void Increment()
{
Count++;
}
}

外部から勝手にCountを書き換えられないため、安全に状態を管理できます。

7-4. 計算プロパティ

計算プロパティは、他の値から計算した結果を返すプロパティです。

C#
public class Circle
{
public double Radius { get; set; }

public double Area
{
get
{
return Radius * Radius * Math.PI;
}
}
}

短く書く場合は、式形式のプロパティも使えます。

C#
public double Area => Radius * Radius * Math.PI;

値を保存するのではなく、必要なタイミングで計算結果を返したい場合に使います。

7-5. staticプロパティ

staticプロパティは、インスタンスごとではなく、クラス全体で共有されるプロパティです。

C#
public class AppSettings
{
public static string ApplicationName { get; set; }
}

使うときは、インスタンスを作らずにクラス名からアクセスします。

C#
AppSettings.ApplicationName = "Sample App";
Console.WriteLine(AppSettings.ApplicationName);

アプリケーション全体で共通する設定値などに使われることがあります。

7-6. requiredプロパティ

requiredは、オブジェクト作成時に必ず値を設定させたいプロパティに使います。

C#
public class Person
{
public required string Name { get; set; }
public int Age { get; set; }
}

この場合、Nameを設定せずにオブジェクトを作成しようとするとエラーになります。

C#
Person person = new Person
{
Name = "Taro",
Age = 20
};

requiredは、必須項目を明確にしたいときに便利です。

特に、オブジェクト初期化子を使うクラスで「このプロパティは必ず設定してほしい」という意図を表現できます。

8. 初心者が混乱しやすいポイント

8-1. プロパティとフィールドは同じものではない

プロパティとフィールドは似ていますが、同じものではありません。

フィールドは値を保存するための変数です。

C#
private string name;

プロパティは、値を取得したり設定したりするための仕組みです。

C#
public string Name { get; set; }

自動実装プロパティではフィールドを書かないため、フィールドと同じように見えるかもしれません。

しかし、プロパティはgetsetを通じてアクセスされる点が異なります。

8-2. get/setは必ず両方書く必要があるのか

プロパティにgetsetを必ず両方書く必要はありません。

読み取りだけにしたい場合は、getだけで書けます。

C#
public string Name { get; }

書き込みを制限したい場合は、private setを使えます。

C#
public string Name { get; private set; }

初期化時だけ値を設定したい場合は、initを使えます。

C#
public string Name { get; init; }

プロパティの目的に応じて、getsetprivate setinitを使い分けることが大切です。

8-3. プロパティ名は大文字で始めるのが一般的

C#では、publicなプロパティ名は大文字で始めるのが一般的です。

C#
public string Name { get; set; }
public int Age { get; set; }

一方、privateフィールドは小文字やアンダースコア付きで書かれることが多いです。

C#
private string name;
private int _age;

たとえば、次のように使い分けます。

C#
private string name;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

プロパティ名を大文字で始めることで、C#の一般的な命名規則に沿った読みやすいコードになります。

8-4. get/setの中に複雑な処理を書きすぎない

プロパティのgetsetには処理を書けますが、複雑な処理を書きすぎるのは避けた方がよいです。

プロパティは、使う側から見ると変数のように見えます。

C#
var name = person.Name;

そのため、プロパティを読み取るだけで重い処理が実行されると、コードを読む人が予想しにくくなります。

たとえば、時間のかかる処理や外部通信、データベースアクセスなどは、プロパティではなくメソッドにした方がわかりやすい場合があります。

C#
public string GetUserNameFromDatabase()
{
// 時間のかかる処理
}

プロパティには、値の取得、簡単な計算、簡単なチェック程度の処理を書くのが基本です。

8-5. Javaのgetter/setterメソッドとの違い

Javaでは、値を取得したり設定したりするために、次のようなgetter/setterメソッドを書くことが一般的です。

Java
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

C#では、同じような役割をプロパティで表現できます。

C#
public string Name { get; set; }

使う側も、メソッド呼び出しではなく、変数のように書けます。

C#
person.Name = "Taro";
Console.WriteLine(person.Name);

ただし、内部的にはgetsetの処理を持てるため、Javaのgetter/setterメソッドに近い役割を果たします。

C#のプロパティは、Javaのgetter/setterをより自然に、簡潔に書ける仕組みだと考えると理解しやすいです。

まとめ

C#のPropertiesは、クラスの値を安全に読み書きするための重要な仕組みです。

基本形は次のように書きます。

C#
public string Name { get; set; }

このような自動実装プロパティは、C#で非常によく使われます。

値を取得するときはget、値を設定するときはsetが使われます。

C#
private int age;

public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
throw new ArgumentException("年齢は0以上である必要があります。");
}

age = value;
}
}

プロパティを使うことで、フィールドを直接公開せずに、値の取得や設定をコントロールできます。

初心者はまず、次の3つを覚えるとよいでしょう。

C#
public string Name { get; set; }
public string Name { get; private set; }
public string Name { get; init; }

{ get; set; }は読み書き可能、private setは外部から変更不可、initは初期化時だけ設定可能です。

C# Propertiesを理解すると、クラス設計、カプセル化、データ保護の考え方が身につきます。C#で実用的なプログラムを書くために、プロパティは必ず押さえておきたい基本機能です。