C#学習基本概念の静的クラスと静的クラスメンバー


静的クラスは非静的クラスとほぼ同じですが、静的クラスはインスタンス化できません.すなわち,newキーワードを用いて静的クラスタイプの変数を作成することはできない.インスタンス変数がないため、クラス名自体を使用して静的クラスのメンバーにアクセスします.たとえば、UtilityClassという名前の静的クラスにMethodAという共通のメソッドがある場合、このメソッドは次の例で呼び出されます.
UtilityClass.MethodA();

入力パラメータのみを演算して内部インスタンスフィールドを取得または設定しないメソッドセットの場合、静的クラスは、これらのメソッドセットのコンテナとして便利に使用できます.例えば、.NET Frameworkクラスライブラリでは、静的クラス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 Framework共通言語ランタイム(CLR)は、静的クラスのタイプ情報をロードします.プログラムは静的クラスをロードする正確な時間を指定できません.ただし、プログラムでクラスを最初に参照する前にクラスをロードし、クラスのフィールドを初期化し、静的構造関数を呼び出すことを保証できます.静的コンストラクション関数は1回のみ呼び出され、プログラムが存在するアプリケーションドメインの生存期間中、静的クラスはメモリに保持されます.
独自のインスタンスの作成のみを許可する非静的クラスを作成するには、「Implementing Singleton in C#(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());
                Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);                   
                 break;                
                 case "2":
                Console.Write("Please enter the Fahrenheit temperature: ");
                C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine());
                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中間言語(MSIL)で生成され、インスタンスメソッドの呼び出しはnullオブジェクト参照もチェックされるcallvirt命令を生成する.しかし、両者のパフォーマンスの違いは、ほとんどの場合明らかではありません.
    備考:転入先https://msdn.microsoft.com/zh-cn/library/79b3xss3.aspx