静的クラスと静的クラス メンバー (C# プログラミング ガイド)

静的クラスは基本的には非静的クラスと同じですが、静的クラスはインスタンス化できないという点が異なります。 つまり、new 演算子を使用して、そのクラス型の変数を作成することはできません。 インスタンス変数がないため、静的クラスのメンバーにアクセスするには、クラス名自体を使用します。 たとえば、UtilityClass という静的クラスがあり、MethodA というパブリック静的メソッドが定義されている場合、このメソッドを呼び出すには次の例のようにします。

UtilityClass.MethodA();  

静的クラスは、入力パラメーターに対してのみ処理を行い、内部のインスタンス フィールドを取得したり設定したりする必要のない一連のメソッドを格納する、便利なコンテナーとして使用できます。 たとえば、.NET クラス ライブラリでは、静的クラス System.Math に、数値演算を実行するメソッドが含まれており、Math クラスの特定のインスタンスに固有のデータを格納または取得する必要はありません。 つまり、次の例に示すように、クラス名とメソッド名を指定して、クラスのメンバーを適用します。

double dub = -3.14;  
Console.WriteLine(Math.Abs(dub));  
Console.WriteLine(Math.Floor(dub));  
Console.WriteLine(Math.Round(Math.Abs(dub)));  
  
// Output:  
// 3.14  
// -4  
// 3  

すべてのクラス型の場合と同様に、静的クラスの型情報が読み込まれるのは、.NET ランタイムで、そのクラスを参照しているプログラムが読み込まれるときです。 プログラムでは、クラスが読み込まれるタイミングを正確に指定することはできません。 ただし、クラスがプログラム内で最初に参照される前に、そのクラスが読み込まれ、そのフィールドが初期化され、その静的コンストラクターが呼び出されることが保証されます。 静的コンストラクターは一度だけ呼び出され、静的クラスは、プログラムが存在するアプリケーション ドメインの有効期間にわたってメモリに保持されます。

注意

インスタンスの作成を 1 つしか許可しない非静的クラスを作成する場合は、「C# でのシングルトンの実装」を参照してください。

静的クラスの主な特徴を以下に示します。

したがって、静的クラスを作成することと、静的メンバーとプライベート コンストラクターのみを含むクラスを作成することは、基本的に同じです。 プライベート コンストラクターは、クラスのインスタンス化を防ぎます。 静的クラスを使用する利点は、インスタンス メンバーが誤って追加されないことをコンパイラで確認できるという点です。 コンパイラは、このクラスのインスタンスを作成できないことを保証します。

静的クラスはシールドされるため、継承できません。 Object 以外のクラスやインターフェイスから継承することはできません。 静的クラスには、インスタンス コンストラクターを含めることができません。 ただし、静的コンストラクターを含めることができます。 特別な初期化を必要とする静的メンバーがクラスに含まれている場合は、非静的クラスであっても静的コンストラクターを定義する必要があります。 詳細については、「静的コンストラクター」を参照してください。

次に、温度を摂氏から華氏に、またはその逆に変換する 2 つのメソッドを含む静的クラスの例を示します。

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;
    }

    public static double FahrenheitToCelsius(string temperatureFahrenheit)
    {
        // Convert argument to double for calculations.
        double fahrenheit = Double.Parse(temperatureFahrenheit);

        // Convert Fahrenheit to Celsius.
        double celsius = (fahrenheit - 32) * 5 / 9;

        return celsius;
    }
}

class TestTemperatureConverter
{
    static void Main()
    {
        Console.WriteLine("Please select the convertor direction");
        Console.WriteLine("1. From Celsius to Fahrenheit.");
        Console.WriteLine("2. From Fahrenheit to Celsius.");
        Console.Write(":");

        string? selection = Console.ReadLine();
        double F, C = 0;

        switch (selection)
        {
            case "1":
                Console.Write("Please enter the Celsius temperature: ");
                F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine() ?? "0");
                Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                break;

            case "2":
                Console.Write("Please enter the Fahrenheit temperature: ");
                C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine() ?? "0");
                Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                break;

            default:
                Console.WriteLine("Please select a convertor.");
                break;
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Example Output:
    Please select the convertor direction
    1. From Celsius to Fahrenheit.
    2. From Fahrenheit to Celsius.
    :2
    Please enter the Fahrenheit temperature: 20
    Temperature in Celsius: -6.67
    Press any key to exit.
 */

静的メンバー

非静的クラスには、静的メソッド、フィールド、プロパティ、またはイベントを含めることができます。 静的メンバーは、クラスのインスタンスが存在しない場合でも、クラスで呼び出すことができます。 静的メンバーには、必ずインスタンス名ではなくクラス名でアクセスします。 クラスのインスタンスの作成数に関係なく、静的メンバーのコピーは 1 つしか存在しません。 静的メソッドと静的プロパティは、それを含んでいる型の非静的フィールドや非静的イベントにはアクセスできません。また、メソッド パラメーターに明示的に渡されない限り、どのオブジェクトのインスタンス変数にもアクセスできません。

クラス全体を静的として宣言するよりも、非静的クラスを宣言して、いくつかの静的メンバーを含める方が一般的です。 静的フィールドの一般的な 2 つの用途は、インスタンス化されたオブジェクトの数を保持することと、すべてのインスタンスで共有する必要のある値を保存することです。

静的メソッドのオーバーロードはできますが、オーバーライドはできません。これは、静的メソッドがクラスのインスタンスではなくクラスに属しているためです。

フィールドを static const として宣言することはできませんが、const フィールドは、その動作において本質的に静的です。 これは、型のインスタンスではなく、型に属します。 そのため、const フィールドにアクセスするには、静的フィールドに対して使用するのと同じ ClassName.MemberName 表記を使用します。 オブジェクト インスタンスは必要ありません。

C# では、静的なローカル変数 (つまり、メソッドのスコープで宣言された変数) はサポートされません。

静的クラスのメンバーを宣言するには、次の例に示すように、メンバーの戻り値の型の前で static キーワードを使用します。

public class Automobile
{
    public static int NumberOfWheels = 4;

    public static int SizeOfGasTank
    {
        get
        {
            return 15;
        }
    }

    public static void Drive() { }

    public static event EventType? RunOutOfGas;

    // Other non-static fields and properties...
}

静的メンバーは初めてアクセスされる前に初期化されます。また、静的コンストラクターがある場合は、それが呼び出される前に初期化されます。 静的クラスのメンバーにアクセスするには、次の例に示すように、変数名の代わりにクラス名を使用してメンバーの位置を指定します。

Automobile.Drive();
int i = Automobile.NumberOfWheels;

クラスに静的フィールドが含まれている場合は、クラスが読み込まれたときに静的フィールドを初期化する静的コンストラクターを用意します。

静的メソッドの呼び出しでは、Microsoft Intermediate Language (MSIL) の call 命令が生成されます。これに対して、インスタンス メソッドの呼び出しでは callvirt 命令が生成され、null オブジェクト参照もチェックされます。 ただし、ほとんどの場合、2 つの間にパフォーマンス上の違いはそれほどありません。

C# 言語仕様

詳しくは、「C# 言語仕様」で静的クラス静的およびインスタンス メンバー静的コンストラクターをご覧ください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。

関連項目