静的メンバ
- 特定のインスタンスにではなく,クラスに属するフィールドやメソッド,プロパティのこと.
static修飾子をつけると静的メンバを宣言できる.- 静的メンバはアプリケーションにただ1つだけ生成され,すべてのインスタンスの間で共有される.
- 静的メンバへのアクセスには,クラスインスタンスを生成するのではなく,クラス名を直接指定する.
- 静的フィールドの初期化には,静的コンストラクターを利用する.
- 通常のコンストラクターがインスタンス生成時に毎回呼び出されるのに対して, 静的コンストラクターはそのクラスの何れかのメンバに初めてアクセスしたときに1度だけ呼び出される.
- 静的メンバから,通常のインスタンス変数やインスタンスメソッドへはアクセスできない.
実装例:静的メンバの作成
- 「果物」を表す
Fruitクラスに対し,番号プロパティint Id, 名前プロパティstring Name,コンストラクタ,文字列変換メソッドstring ToString()を与える.- これらは,インスタンスに依存する通常のローカルメンバであり,インスタンス毎に異なる値を持つ.
- 番号から果物への単射影を管理するための
private静的フィールドDictionary<int, Fruit> _fruitsを与える. - 静的コンストラクタを用意し,
_fruitsへ初期値を与える. - 番号指定で
Fruitクラスインスタンスを作成するためのFromId(int id)静的メソッドを与える.- これらの静的メンバは,インスタンスに依存せずクラス間で共有される.
Fruit.cs
/// <summary>/// 果物を表します./// </summary>publicclassFruit{/// <summary>/// 番号/// </summary>publicintId{get;set;}/// <summary>/// 名前/// </summary>publicstringName{get;set;}/// <summary>/// 果物図鑑 ※静的メンバ(=クラス間で共通)/// </summary>privatestaticDictionary<int,Fruit>_fruits{get;set;}/// <summary>/// コンストラクタ ※静的メンバにはアクセス不可/// </summary>/// <param name="id">番号</param>/// <param name="name">名前</param>publicFruit(intid,stringname){this.Id=id;this.Name=name;}/// <summary>/// 静的コンストラクタ ※静的メンバのみにアクセス可能/// </summary>staticFruit(){// 果物図鑑を作成_fruits=newFruit[]{newFruit(1,"りんご"),newFruit(2,"いちご"),newFruit(3,"メロン")}.ToDictionary(f=>f.Id,f=>f);}/// <summary>/// 現在のオブジェクトを表す文字列を返します./// </summary>publicoverridestringToString(){return$"{this.Id:00}:{this.Name}";}/// <summary>/// 番号を指定して果物図鑑からインスタンスを取得します./// </summary>/// <param name="id">番号</param>publicstaticFruitFromId(intid){return_fruits[id];}}実装例:メンバへのアクセス方法
- 通常のローカルメンバは,クラスインスタンスから呼び出しを行う.
- 静的メンバは,クラスをインスタンス化せず,[クラス名.メンバ]の記載形式で呼び出しを行う.
FruitAccessor.cs
privatevoidTest(){// 通常のプロパティやメソッドは,クラスをインスタンス化してからアクセスvarfruit1=newFruit(4,"パイナップル");varid=fruit1.Id;// int[4] vardisplay=fruit1.ToString();// string["04:パイナップル"]// 静的メンバは,クラスをインスタンス化せず,[クラス名.メンバ]の記載形式でアクセスvarfruit2=Fruit.FromId(2);// Fruit[Id = 2, Name = "いちご"]varfruit3=Fruit.FromId(3);// Fruit[Id = 3, Name = "メロン"]}静的クラス
- 静的メンバしか定義できないクラス.
- クラスの前に
static修飾子を付けて宣言する. - インスタンスの作成が不可能なクラスを作る場合に利用する.
- 別言語では moduleと呼ばれ区別されることもある.
staticの活用
- 例えば,
readonlyでないpublicな静的フィールドはどこからでも書き換えられる可能性があり,むやみな使用は控えるべきである. - 以下に,
static修飾子の活用方法を幾つか示す.
ユーティリティ(ヘルパー)クラスとしての活用
- 複数の箇所から利用される汎用的な処理等,共通の機能を提供するために静的クラスを利用する.
グローバル定数としての活用
- 定数値のシンボル名が必要で,その値の型を
const宣言で使用できない場合,またはその値をコンパイル時に計算できない場合はstatic readonlyフィールドを利用する. constは,属性に指定するパラメータや列挙型の定義など,コンパイル時に値が必要な場合にのみ使用する.
| フィールド | 値の決定 | 実行速度 | switch文 | 値の割当 |
|---|---|---|---|---|
| const | コンパイル時 | readonlyより速い | 利用可 | インスタンスを new した結果は割当不可 |
| static readonly | 実行時 | constより僅かに遅い | 利用不可 | インスタンスを new した結果を割当可能/コンストラクタで初期化可能 |
拡張メソッド
- 通常の前置き記法である静的メソッドを,インスタンスメソッドと同様に後置き記法で書くことができる.
- 拡張メソッドの作成には,静的クラスに対して静的メソッドを実装し,先頭の引数に対して
this修飾子を付与する.
Extensions.cs
publicstaticclassExtensions{/// <summary>/// System.Collections.Generic.IEnumerable`1 型の構築された System.String コレクションのメンバーを連結します.各メンバーの間には,指定した区切り記号が挿入されます./// </summary>/// <param name="values">連結する文字列を格納しているコレクション.</param>/// <param name="separater">区切り文字として使用する文字列.戻される文字列に separator が含まれるのは,values に複数の要素がある場合のみです.</param>/// <returns>values のメンバーからなる,separator 文字列で区切られた文字列. values にメンバーがない場合,メソッドは System.String.Emptyを返します.</returns>publicstaticstringJoin(thisIEnumerable<string>values,stringseparater){returnstring.Join(separater,values);}}ExtensionsTester.cs
privatevoidTest(){varpieces=newList<string>(){"飛車","角","金","銀","桂馬","香車"};// 通常の静的メソッド呼び出し(前置き記法)vardisplay1=string.Join(", ",pieces);// string["飛車, 角, 金, 銀, 桂馬, 香車"]// 拡張メソッド呼び出し(後置き記法)vardisplay2=pieces.Join(", ");// string["飛車, 角, 金, 銀, 桂馬, 香車"]}