staticを理解しよう!

[C#] staticを理解しよう!

※ 当サイトは広告を含みます。

ここではC#のstaticについて学びます。

static

staticは静的クラスや静的メンバを作成する時に利用します。

実はサンプルで既に利用していて、Main関数がstatic宣言されてます。


static void Main(string[] args)

では、このstaticは何を意味するのでしょうか?
静的とは「動かない」とか「一定」と言う意味らしいです。

より簡単に言うと、staticを付けたクラスやメソッドはアプリケーションで1つだけの存在(共通利用)になります。
以前にクラスは設計図、インスタンスを生成しないと使えないと言いましたが、staticを付けるとインスタンスを生成しなくても使えます。

りさ
りさ

だからインスタンスを生成しなくてもMain関数は動いてたんですね。

管理人
管理人

そうだよ。

その代わり共通利用されるので、全ての処理で同じクラスやメソッドが呼び出されます。
特に分かりやすいのがフィールドでしょう。試しに以下のサンプルコードを実行してください。


namespace Sample
{
  public class Counter
  {
    private static int count = 0; // staticフィールド

    public void Up()
    {
      count++;
    }

    public void Display()
    {
      System.Console.WriteLine(count);
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      var c1 = new Counter();
      var c2 = new Counter();

      c1.Display();
      c2.Display();

      c1.Up();

      c1.Display();
      c2.Display();
    }
  }
}

このようにstaticを付けたcount(フィールド)は複数のインスタンスから共通利用されます。
これが単なる非staticフィールドであれば、UP()メソッドが作用するのは自身のインスタンスのみです。
しかし、staticを付けたことでアプリケーションで唯一の存在になり、値が共通化されました。

管理人
管理人

staticを付ける対象で微妙に動作は異なりますが、根本はアプリケーションで1つの存在になることです。
仮にメソッドやプロパティに付ければ、インスタンスを生成しなくても呼び出せる機能を作れます。

アクセス方法

.(ドット)演算子を利用する部分は同じですが、インスタンスを生成しないため通常のアクセス方法とは微妙に異なります。
これは例を見たほうが分かりやすいと思います。先に以下のサンプルコードを実行してください。


namespace Sample
{
  public class Display
  {
    public static void Output()
    {
      System.Console.WriteLine("りさ");
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      Display.Output(); // staticメソッドにアクセス
    }
  }
}

こんな感じにインスタンス名ではなくクラス名を利用してアクセスします。
部分的に抜き出すと以下ですね。クラス名.メソッドって感じです。


Display.Output();

実は何度も登場してるSystem.Console.WriteLine()も同様の仕組みです。
これはSystem名前空間に存在するConsoleクラスWriteLineメソッドにアクセスしてます。

static class

少し特殊なのがクラス自体にstaticを付ける場合です。

メソッドやフィールドであれば、それ単体が唯一の存在になりましたが、クラスに付けるとクラスの全てがstaticになります。
ただし、その代わり恐ろしく厳しい制約が付くので、安易に付けると設計不能になって色々と崩壊します。

先に課せられる制約は以下です。

  1. staticメンバ(メソッドやフィールド等)しか実装できない
  2. インスタンスが生成できない
  3. 継承できない(シール化される)

まだ、知らない単語もありますが、この中でも継承できないが最も厳しい制約です。
C#にはポリモーフィズムと呼ばれる神みたいな機能があって、それを担うのが継承の仕組みです。

がっ、staticを付けたクラスは継承自体ができなくなるので、その仕組みに乗りません。
C#は継承を利用して最高の設計ができる言語なんですが、それを真っ向から否定されてる感じがします。

管理人
管理人

過去にどんな罪を犯せばこんな制約が付くのか、まるで重罪人だよ。

りさ
りさ

それでも利用されてるってことは必要な機能なんですよね?

管理人
管理人

理解して使うなら便利だよ。まぁ、僕はstaticクラスは殆ど使わないけど。

static コンストラクタ

staticクラスはインスタンスが生成できない都合でコンストラクタが使えません。
その代わりに利用できるのがstaticコンストラクタです。これは名前の通りでstaticクラス用のコンストラクタです。

まずはサンプルコードで動作を確認しましょう。


namespace Sample
{
  public class Display
  {
    private static string name;

    // static コンストラクタ
    static Display()
    {
      name = "りさ";
    }

    public static void Output()
    {
      System.Console.WriteLine(name);
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      Display.Output();
    }
  }
}

staticが付いてるので、このコンストラクタにも制約があります。
具体的には以下なんですが、結論として1種類の記述しかできません。

  1. アクセス修飾子を記述できない
  2. 引数を付けることはできない

その結果、こんな感じの記述のみに対応します。


static クラス名()
{
}

また、普通のコンストラクタはインスタンス化したタイミングで呼び出されますが、そもそもstaticクラスはインスタンス化できません。
それもあり、staticコンストラクタは初めてstatic関連のメンバにアクセスした時、自動的に呼び出される仕様になってます。

管理人
管理人

つまりstaticメンバにアクセスする場合、事前にstaticコンストラクタが呼び出されることは必ず保証されます。

static利用時の注意

これは注意というより当然の結果なんですが、staticメンバはstaticなメンバにしかアクセスできません。
例えばstaticメソッドがあったとして、そのメソッドでインスタンスが所有する通常のフィールドにはアクセスできません。

これはstaticメソッドがインスタンス化を必要としない特性から、staticメソッドの利用時にインスタンスの存在が保証できないからです。
この様に絶対の確約がない情報は全てビルドエラーとして扱われます。これに関しては冷静にパターンを考えれば分かるので、ここでの説明は省きます。

あとがき

staticを利用する判断は経験を積まないと分からないと思います。特にstaticクラスなんかは余程の理由がなければ使いません。
C#はオブジェクト指向と呼ばれるインスタンスを利用する手法が基本です。なので、迷うくらいなら使わないほうがいいです。

◆ C#に関する学習コンテンツ

この記事は参考になりましたか?

関連記事

コメント

この記事へのコメントはありません。