C#を勉強しなおしてみた(2)
プロパティとフィールド

どもです。

前回に引き続き、今回もC#のお勉強について書いていきます。

今回は、C#の「プロパティ」と「フィールド」について書いていきます。

1. フィールド

まず「フィールド」についてです。

フィールドとは、一言で言ってしまえば、「メンバ変数」です。クラスや構造体が含む、任意の型の変数のことを、C#では「フィールド」と呼びます。

1.1. フィールドへのアクセス

フィールドを使用する際に、そのアクセシビリティ、要は「アクセス修飾子」「アクセスレベル」にはprivateまたはprotectedを指定します。publicは指定しません。

フィールドにアクセスする際には、対応するメソッド、またはプロパティからアクセスします。

このように、フィールドへのアクセスを制限することで、フィールドに対して、予期せぬ値、不正な値が設定されることを回避、防止できます。

1.2. 静的フィールド

フィールドには、「静的フィールド」と呼ばれるフィールドがあります。このフィールドは、「static」を付与することで宣言することで定義します。

「静的フィールド」と通常の「フィールド」の違いですが、静的フィールドは「オブジェクトが存在しなくても参照できる」ということです。クラスをインスタンス化(newする)しなくても、このフィールドにアクセスができます。また、この「静的フィールド」は、1つだけしか存在しない、という特徴を持ちます。

2. プロパティ

次に、「プロパティ」です。

プロパティを一言で表すならば、「getter/setter」です。

フィールドでも「ちらっ」とだけ書きましたが、フィールドはアクセシビリティが「protected」または「private」に設定されており、外部からアクセスができません。そのため、この「フィールド」にアクセスするために使用するのが「プロパティ」です。

2.1. プロパティの実装

プロパティは、例えば以下のように実装します。

public class Worker
{
	protected int _id = 0;
	protected string _name = string.Empty;

	public int ID
	{
		get {
			return _id;
		}
		set {
			_id = value;
		}
	}
	public string Name
	{
		get{
			return _name;
		}
		set {
			_name = value;
		}
	}
}

上記のコードでのIDNameが「プロパティ」に該当します。

2.2. プロパティのシンプルな実装

プロパティの実装で示したコードは、実はもっと簡単にできます。簡単にしたコードは、以下の通りです。

public class Worker
{
	public int ID { get; set; }
	public string Name { get; set; }
}

このコードをプロパティの実装のコードと比較して分かる違いとして、フィールドがないということが挙げられます。

プロパティが、単にgetter/setterとしての役割のみであれば、プロパティを通してアクセスしたいフィールドの宣言は省略できます。なおこれは、自動実装するプロパティと呼ばれ、msdnでは以下のように説明されています。

プロパティ アクセサーに追加のロジックが必要ない場合は、自動実装プロパティを使用することで、プロパティをより簡潔に宣言できます。 これにより、クライアント コードでオブジェクトを作成することも可能になります。 次の例に示すようにプロパティを宣言する場合、コンパイラによって、プロパティの get および set アクセサーを介してのみアクセスできる、プライベートの匿名バッキング フィールドが作成されます。

詳細は、msdnを参照してください。

この説明での「次の例」は省略しますが、大きくは先述のコードと重要な点は同じです。

2.3. 静的プロパティ

プロパティもフィールドと同様、「静的」プロパティを定義できます。定義の方法はフィールドと同様で、型の前に「static」を付与するのみです。

2.4. プロパティの使いどころ

ここまでの内容では、「フィールドは不要では?」「全部プロパティでいいのでは!?」という印象を受けるかもしれません。しかし、そうではありません。先述の通り、「フィールドに不正な値が代入されることを回避する」ための判定、チェック処理を実現することはもちろんですが、それ以外の使いどころとして、「フィールドの値が変更されたことを、他のオブジェクトに通知したい場合」があります。

具体的なコードを書いてみます。

public class Worker
{
	public delegate RaiseIdChangeEventHandler(object sender, IdChangedEventArg e)
	public event RaiseIdChangeEventHandler RaiseIdChanged;

	protected int _id = 0;
	public int ID
	{
		get => _id;
		set
		{
			_id = value;
			RaiseIdChanged?.Invoke(this, new IdChangedEventArg(_id));
		}
	}
}

こうすることで、プロパティIDの値が更新されたことを複数のオブジェクトに対して通知することができます。

3. まとめ

今回は、C#の「プロパティ」と「フィールド」についてかきました。

プロパティとフィールドは、それぞれ以下のようなモノになります。

  • フィールド
    • いわゆる「メンバ変数」
    • (通常)アクセスレベルはprivateまたはprotectedに設定され、外部からはアクセスできない。
    • 「static」を付与することで「静的」フィールドとすることができる。
      (「静的」フィールドは、インスタンス化しなくても存在、アクセスが可能な変数)
  • プロパティ
    • いわゆる「getter」「setter」
    • プロパティを介してアクセスする「フィールド」への操作が値の代入、あるいは参照のみの場合、「自動実装するプロパティ」によりフィールドの実装を省略できる。
    • 「static」を付与することで、「静的」プロパティを定義することができる。
    • プロパティは、フィールドに不正な値が設定され内容にするための判定処理を担う場合がある
    • プロパティは、フィールドの値が更新されたことを複数オブジェクトに通知する際に使用する

プロパティ、フィールドは、もちろんコレだけではありません。今回書いた内容は、あくまで「基本の『キ』の中の更に『キ』」だと思います。それを理解してお勉強あるいは開発を進めるのがよいかと思います。

ではっ!