Unity & C# 学習教材

static メンバーと static クラス

クラスのメンバーには、各インスタンスごとに持つものと、クラス全体で共有するものがあります。static は「インスタンスではなく型に属する」ことを表すキーワードです。

学習目標

前提知識


1. インスタンスメンバーと static メンバーの違い

インスタンスメンバーは、各インスタンスに独立して存在します。static メンバーはクラスに属し、すべてのインスタンスで共有されます。

インスタンスを生成しなくても使えるのが static メンバーの特徴です。


2. static フィールド

書式:static フィールド

1
アクセス修飾子 static 型 フィールド名;
要素 説明
static クラスに属するフィールドであることを示す
保存する値の型
フィールド名 共有される変数の名前

static int Count; と書くと、すべてのインスタンスから同じ Count を見ます。


3. static メソッド

書式:static メソッド

1
2
3
4
アクセス修飾子 static 戻り値の型 メソッド名()
{
    処理
}
要素 説明
static クラスに属するメソッドであることを示す
戻り値の型 メソッドが返す値の型
メソッド名 クラス名から呼び出すメソッド名

static メソッドは クラス名.メソッド名() で呼び出します。インスタンスに属さないので、メソッド本体に this は存在しません。


4. static コンストラクタ

書式:static コンストラクタ

1
2
3
4
static クラス名()
{
    処理
}
要素 説明
static 型初期化用のコンストラクタであることを示す
クラス名 対象のクラス名

static コンストラクタは、その型が最初に使われるときに一度だけ自動実行されます。パラメータなしアクセス修飾子なしがルールです。


5. static class

書式:static クラス

1
2
3
4
static class クラス名
{
    static メンバー
}
要素 説明
static class クラス全体を static にする宣言
static メンバー クラス内に置けるメンバー。すべて static でなければならない

static class はインスタンス化できません。クラスのすべてのメンバーを static に限定したいときに使います。


6. 実行例

Id はインスタンスフィールド、Countstatic フィールドです。それぞれの振る舞いの違いをまとめて確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A
{
    public int Id;                     // インスタンスフィールド(各インスタンスが独立して持つ)
    public static int Count = 0;       // static フィールド(全インスタンスで共有される)

    static A()
    {
        Console.WriteLine("A.static_ctor");
    }

    public A(int id) { Id = id; Count++; }

    public static void M()
    {
        Console.WriteLine($"A.M: Count={Count}");
    }
}

A.M();                      // インスタンス不要
var a1 = new A(1);
var a2 = new A(2);
A.M();                      // Count=2
Console.WriteLine($"a1.Id={a1.Id}, a2.Id={a2.Id}");  // Id は独立
1
2
3
4
A.static_ctor
A.M: Count=0
A.M: Count=2
a1.Id=1, a2.Id=2

Counta1a2 の両方の生成で更新されていますが、Ida1a2 でそれぞれ独立した値を持っていることがわかります。static コンストラクタは最初の A.M() 呼び出し時に一度だけ実行されます。

static class の例

1
2
3
4
5
6
7
static class B
{
    public static void M() { Console.WriteLine("B.M"); }
}

B.M();
// new B(); // ❌ インスタンス化できない
1
B.M

よくあるミス

ミス①:static メソッドの中でインスタンスメンバーに直接アクセスする

1
2
3
4
5
6
7
8
9
10
11
class A
{
    public int Value;

    // ❌ NG: static メソッドの中に this はない
    // public static void M() { Console.WriteLine(this.Value); }

    // ✅ OK: static メソッドでは static メンバーだけを直接使う
    public static int Count;
    public static void M() { Console.WriteLine($"A.M: Count={Count}"); }
}

ミス②:static コンストラクタにアクセス修飾子を書く

1
2
3
4
5
6
7
8
class A
{
    // ❌ NG: static コンストラクタに public/private は書けない
    // public static A() { Console.WriteLine("A.static_ctor"); }

    // ✅ OK: アクセス修飾子なしで書く
    static A() { Console.WriteLine("A.static_ctor"); }
}

まとめ


理解度チェック

以下の問いに答えられるか確認しましょう。

  1. インスタンスメンバーと static メンバーの違いは何ですか?
  2. 次のコードの出力結果は何になりますか?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    class A
    {
        public static int Count = 1;
    
        public A() { Count++; }
    
        public static void M()
        {
            Console.WriteLine($"A.M: Count={Count}");
        }
    }
    
    A.M();
    var a = new A();
    A.M();
    
  3. static class B の中に public static void M() を定義し、"B.M" を表示するコードを書いてください。
解答を見る
  1. インスタンスメンバーは各オブジェクトごとに持つ値で、static メンバーはクラス全体で共有される値です。
  2. 1
    2
    
       A.M: Count=1
       A.M: Count=2
    
  3. 1
    2
    3
    4
    5
    6
    7
    8
    9
    
    static class B
    {
        public static void M()
        {
            Console.WriteLine("B.M");
        }
    }
    
    B.M();
    

次のステップ

拡張メソッド では、既存の型にメソッドを追加したように見せる書き方を学びます。