staticの付いている変数や関数は一体何者なのか。
staticは「静的なもの」という意味があります。
静的なものとはどういうことなのか、実際に作って処理を見てみましょう
静的な変数・関数
静的な変数や関数は、ざっくり一口で行ってしまうと、変数、関数を呼び出すのにクラスをnewしてインスタンスを作成する必要なく呼び出すことができます。
逆に、newして作成されたインスタンスからは呼び出せません。
変数
static変数とstaticではない変数を作成して違いを見てみます。
1 2 3 4 5 |
public class Foo { public static string staticText = "StaticText"; public string dynamicText = "DynamicText"; } |
クラスFooのstaticTextとdynamicTextを別のクラスから呼び出してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Bar { public Bar() { var staticText = Foo.staticText; // var dynamicText = Foo.dynamicText; コンパイルエラー var foo = new Foo(); var dynamicText = foo.dynamicText; Console.WriteLine(staticText); Console.WriteLine(dynamicText); } } // 出力結果 // StaticText // DynamicText |
静的な変数のstaticTextはFooクラスから直接呼び出すことができます。
対して、dynamicTextをFooクラスから直接呼び出すとコンパイルエラーとなりました。
dynamicTextはFooクラスのインスタンスからしか呼び出すことができません。
注意点として、このstaticな変数は値を変更すると、以降変更値が保持されてしまうので思わぬ不具合の原因になってしまう恐れがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
namespace CharpTraining.BusinessLogic { public class Bar { public Bar() { Console.WriteLine(Foo.staticText); Foo.staticText = "静的変数の値変更"; var hoge = new Hoge(); } } public class Hoge { public Hoge() { Console.WriteLine(Foo.staticText); } } } // 実行結果 // StaticText // 静的変数の値変更 |
変更させたくない場合は、public static readonly のようにして読み込み専用変数にしておくと安心です。
関数
関数も同じく、クラスから直接呼び出すことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Foo { public static string staticMethod() { return "静的な関数"; } } public class Bar { public Bar() { Console.WriteLine(Foo.staticMethod()); } } // 実行結果 // 静的な関数 |
ただし、静的な関数は静的ではないメンバ変数・関数を扱うことができません。
あくまで、静的な処理のみを行う関数として作成する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Foo { public String hoge = "hoge"; public string huga() { return "huga"; } public static string staticMethod() { var huga = huga(); // コンパイルエラー return hoge; // コンパイルエラー } } |
private staticな関数
ちなみに、private staticな関数を見かけることがあります。
これは、「この関数は静的処理のみを行なっている(副作用のない関数)」ということを意味している為、ロジック改修やリファクタリングなどの保守時に影響範囲を掴む為に役立ちます。
静的なクラス
static修飾子はクラスに付けることもできます。
その場合、クラスメンバは全てstaticである必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
static class Foo { public static string hoge = "hoge"; public string aaa = "aaa"; // コンパイルエラー public static string huga() { return "huga"; } public string bbb() // コンパイルエラー { return "bbb"; } } |
終わりに
Microsoftのドキュメントがあります。
詳しくは、こちらを見ると参考になります。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/static