Uenishi.Web

大阪に生息しているプログラマーのブログ

【C#】プロパティとメンバ変数の違い

プロパティとは

クラス外部から見るとメンバー変数のようにふるまい、クラス内部から見るとメソッドのようにふるまうもの。

JavaやC++はこの機能を持っていない。C#が持つ便利な機能。

  • プロパティ: 中(実装側)からはメソッドのように扱え、外(利用側)からはメンバー変数のように見えるもの。
  • 実装の隠蔽(カプセル化)を崩すことなく、アクセサー関数の煩雑さを解消。

参考: https://ufcpp.net/study/csharp/oo_property.html

Javaなどではアクセサーのメソッド名は

String hoge = sampleClass.GetHoge() 

などのように、メソッド名にGetやSetがついた命名のメソッドを呼び出します。

クラス側としては、オブジェクトの状態を操作する際はメソッドを通して行った方が良いためこのようになっていますが、クラス呼び出し側からすると非常に読みづらいものにもなります。

そのため、C#ではプロパティという機能で、クラス呼び出し側からは以下のように呼び出すことができるようになっています

string hoge = sampleClass.Hoge;

Getや()がなく、かなりすっきり読めるようになりました。

これが「クラス利用側から見るとメンバ変数のように振る舞う」という意味合いです。

逆に、クラス内部ではメソッドのように振る舞います。

こちらがどういうことか見ていきます。

プロパティはメンバ変数(フィールド)にアクセスするための手段

メンバ変数はフィールドともいいます。

「プロパティ」とは値そのものをいうのではなく、このメンバ変数にアクセスするための仕組みです。

以下のようなクラスがあったとして

public class Sample
{
	// メンバ変数
	private string name;
	private int age;

	// プロパティ
	public string Name
	{
		get 
		{ 
			return name;
		}
		set
		{
			name = value;
		}
	}
	
	public int Age
	{
		get 
		{ 
			return age;
		}
		set
		{
			age = value;
		}
	}
}

このように、メンバ変数にget, setアクセスするためのメソッドをプロパティと呼びます。

C#の変数宣言はcamelCaseですが、クラス内でプロパティを宣言するときはPascalCaseなので「あれ?」と思っていました。

プロパティはメンバ変数にアクセスするための「メソッドの一種」といえます。

参考: https://www.w2solution.co.jp/tech/2021/05/30/糸賀cにおけるメソッドとプロパティの違/

Tips

メンバ変数とフィールドの違い

基本的には同じ意味で、インスタンス変数を表すときに用いられる。

static修飾子などがついた変数はクラス変数といい、こちらは「静的メンバ」「静的フィールド」などと呼ばれる。

「フィールド」はクラスの視点で見た時の言い方。

メンバ変数は「クラスの中にある(クラスの中でどこからでもアクセスできる)変数」をあらわしたいときの言い方。

みたいな感じで理解していて問題はなさそう。

自動実装プロパティ

C# 3.0より、自動実装プロパティという機能が実装されました。

(現在の最新はC# 10 https://learn.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-10?source=recommendations)

上のようなコードは、以下のように実装しても同じです。

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

かなり省略され、見やすくなりました。

このコードにも前述のコードと同じように、暗黙的に以下のようなprivateのメンバ変数が定義されています。

  private string name;
  private int age;

読み取り専用のプロパティとして設定したい場合は、以下のようにsetにprivateを指定することで、クラス内からしかメンバ変数の値を変更できなくなります。

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

気軽に変更したくないメンバ変数はsetをprivateにすることで、クラス外部から値を変更できなくなり、より安全性の高いクラスを設計できます。

設計についてはまた別の記事にて……

以上です!