C#では、C言語で言うどの関数からでも呼び出せるグローバル関数を作ることができません。これは、C#がクラス言語と呼ばれるもので、グローバル関数はどこからでも呼び出すことができるので、モジュールの結合度が高くなり、これを避けるように配慮された言語だからです。
ではどのような処理を、複数のクラスから呼び出せるクラス、つまりユーティリティクラスとしてまとめるのがよいのでしょうか。次のような設計方針が考えられます。
- 状態を持たない処理をまとめたユーティリティクラス 具体例であげると、「変換前のデータ」を渡すと「変換後のデータ」が手に入ればよく、状態を保持し続ける必要がない処理は、ユーティリティクラス化に向いています。 また、単なる計算や関数などもユーティリティクラス向きです。java.lang.Mathクラスはこの典型であるといえます。
- 業務固有のユーティリティクラス ユーティリティクラスは、特定の業務アプリケーションの中だけで、共通処理を行うものが考えられます。この場合、業務アプリケーション内の複数のクラスから呼び出す共通処理を、ユーティリティクラスとしてまとめます。特定業務固有のユーティリティクラスは「アプリ名+Util(s)」という名前になることが多いようです。 例えば「DP」いうプロジェクトなら「DPUtils」といった具合です。
- Windows フォーム アプリケーションのユーティリティクラス フォームの中で使うメソッドは、そのフォームクラスの private メソッドとして定義すればよく、複数のフォームから使いたいロジックは、ユーティリティクラスにして呼び出して使うのが普通です。
ユーティリティクラスは具体的には次のようにstatic クラスとして作成できます。
public static class TemperatureConverter { public static double CelsiusToFahrenheit(string temperatureCelsius) { // Convert argument to double for calculations. double celsius = Double.Parse(temperatureCelsius); // Convert Celsius to Fahrenheit. double fahrenheit = (celsius * 9 / 5) + 32; return fahrenheit; } }
static クラスは次のような特徴を持ちます。
- static クラスは、動的メンバ変数・動的メソッドは宣言できません。
- static クラスは、継承できません。
- static クラス・メソッドは、継承を前提・想定して使うキーワード (virtual, override, abstract, sealed) を一緒に扱うことはできません。
このstatic クラスを次のように呼び出します。
class TestTemperatureConverter { static void Main() { double C = 0; C = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine()); Console.WriteLine("Temperature in Celsius: {0:F2}", C); } } /* Example Output: Temperature in Celsius: -6.67 */
共通処理ならば、なんでもユーティリティクラスにすればよいわけではありません。 本来ならオブジェクトにしたほうがよいものをユーティリティクラスにすると、インスタンス化し、そのインスタンス固有のプロパティを持たせることができ、オブジェクト指向的な処理を行うことができるメリットを十分に生かせない、融通の利かないプログラムになってしまいます。ユーティリティクラスを作成するときは十分に注意する必要があります。