ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

C# - 静的メンバー(static)

初めに

 C# で書かれたコードの中に static をいうキーワードを見たことがあるかと思います。これは静的メンバーにつけるキーワードになります。本記事では、静的メンバーについてまとめます。



静的メンバーとは

メンバー

 メンバーとは、

クラスや構造体に属する関数やフィールド(変数)などの総称

です。関数、変数、定数、コンストラクター演算子などがメンバーになります。
learn.microsoft.com

静的メンバー

 静的メンバーとは、

特定のインスタンスにではなく、クラスに属するメンバー(変数や関数など)のこと

です。
 
 静的という言葉は、静的メソッド、静的フィールドのような使い方もします。また、静的メソッドや静的フィールドはクラスに属するので、それぞれクラスメソッドやクラスフィールドのようにも呼ばれます。
 対して、通常の変数や関数などのメンバーは各インスタンスに属するため、インスタンスメンバーと呼ばれます。

静的メンバーの定義の仕方

 クラスのメンバーを定義するときに、型名の前に static をつけると、静的メンバーとして定義できます。

(例)

//変数
static int num;
public static string name;

//関数
public static void Method()
{
      //関数の中身は省略
}
静的メンバーの特徴、参照の仕方

 静的メンバーは、クラスに属するメンバーでした。そのため、次のような特徴を持ちます。

静的メンバーはクラスごとに唯一つの実体を持ち、すべてのインスタンスの間で共有される

 クラス全体で共有したいものは静的に、インスタンスごとに設定したいものは今まで通りのメンバーにすればよいです。

 例えば、同じレベルの2体のピカチュウがいたとします。ピカチュウAとピカチュウBのステータスはピカチュウ全体で設定された強さの数値(種族値)と各個体ごとにランダムで与えられる強さの数値(個体値)で決まります。(努力値はは今回の説明に使わないため考えないことにします。)ピカチュウという同じ種族で同じレベルでもピカチュウごとに個体値は異なるため、ピカチュウA、B のステータスは異なります。

 このような状況を作る場合、種族値は種族で共有すべきなので、静的メンバーとして定義すべきです。また、個体値は個体ごとに設定しなければならないので、インスタンスごとに設定するために静的にはしないでしょう。

 また、静的変数はクラスで共通のため、参照の仕方が通常の変数と異なります。

変数の参照の仕方

  • 静的変数:「クラス名.変数名」
  • 通常の変数:「インスタンス名.変数名」

(サンプル)

class Pikachu
{
  //種族の名前や種族値は種族で共通のため, 静的に
  public static string name; // 種族の名前
  public static int BaseHp;  //HPの種族値

  //個体値はインスタンスごとに
  public int IndividualHp;  //HPの個体値
}

>|cs|
Pikachu pika = new Pikachu();

//静的変数は「クラス名.変数名」で参照する
Pikachu.name = "Pikachu";
Pikachu.BaseHp = 35;

//インスタンスメンバーは「インスタンス名.変数名」で参照する
pika.individualHp = 31;
静的メソッド(静的関数)

 定義の仕方は上記の通りです。関数については、数学関数のようにインスタンスごとに分ける必要のないもののほうが多いように感じます。そのような場合にも、静的にし、インスタンスをとることなくクラスから呼び出せるようにします。

静的コンストラクター

 静的フィールドの初期化には、通常のコンストラクターではなく、静的コンストラクターというものを使います。コンストラクターの前に static をつけることで、静的コンストラクターを定義できます。

class Pikachu
{
  //静的メンバー
  public static string name; // 種族の名前
  public static int BaseHp;  //HPの種族値

  //静的コンストラクター
  static Pikachu()
  {
      Pikachu.name = "Pikachu";
      Pikachu.BaseHp = 35;
  }

  //通常の変数
  public int IndividualHp;  //HPの個体値

  //通常のコンストラクター
  public Pikachu(int individualHp)
  {
      this.individualHp = individualHp;
  }
}
//インスタンスを生成するときに、コンストラクタを使って初期化
Pikachu pika = new Pikachu(31);


 通常のコンストラクターが新しいインスタンスが生成されるたびに呼び出されるのに対して、 静的コンストラクターは、そのクラスの何らかのメンバーに初めてアクセスしたときに1度だけ呼び出されます。

静的クラス(C# 2.0)

 C# 2.0 では、 静的クラスと呼ばれるクラスを定義できます。静的クラスとは、

静的メンバーしか定義できないクラス

のことです。クラス定義時に static をつけることで、定義できます。

static class MyClass()
{
  //静的クラスのため、この中では非静的なものは定義できない
}

 例えば、標準ライブラリ(System)の Math クラスは静的クラスになっています。
learn.microsoft.com

using static(C# 6)

 using static ディレクティブを書くことで、クラス名を省略して、直接静的メソッドを呼べるようになります。

(サンプル:System.Mathを使う)
〇using static System.Mathを使う場合

using System;
using static System.Math;

class Sample
{
    static void Main()
    {
        double num = 2 * Asin(1);
    }
}

〇using static System.Math を使わない場合

using System;

class Sample
{
    static void Main()
    {
        double num = 2 * Math.Asin(1);
    }
}

 列挙型(enum)のメンバーも静的のため、using static ディレクティブを書くことで省略できます。
fineworks-fine.hatenablog.com

 また、using static は静的クラスだけでなく、任意のクラスに対して使えます。

最後に

 今回は静的メンバーについてまとめました。静的メンバーとは、インスタンスではなくクラス共通のものであることが分かればよいでしょう。