クラスの概要

参照型

class として定義された型は、"参照型" です。 実行時に、参照型の変数を宣言すると、new 演算子を使用してクラスのインスタンスを明示的に作成するまで、変数には値 null が格納されています。または、次の例に示すように、別の場所で作成された可能性がある、互換性のある型のオブジェクトを代入することもできます。

//Declaring an object of type MyClass.
MyClass mc = new MyClass();

//Declaring another object of the same type, assigning it the value of the first object.
MyClass mc2 = mc;

オブジェクトが作成されると、その特定のオブジェクトに対してマネージド ヒープ上で十分なメモリが割り当てられ、変数にはそのオブジェクトの場所への参照のみが格納されます。 マネージド ヒープを使用する型では、メモリの割り当て時と、CLR の自動メモリ管理機能 ("ガベージ コレクション") による再要求時の両方についてオーバーヘッドが発生します。 しかし、ガベージ コレクションも高度に最適化されるため、ほとんどのシナリオでは、パフォーマンス上の問題が発生することはありません。 ガベージ コレクションの詳細については、「自動メモリ管理とガベージ コレクション」を参照してください。

クラスの宣言

クラスは、次の例に示すように、class キーワードと、その後に続ける一意の識別子を使用して宣言します。

//[access modifier] - [class] - [identifier]
public class Customer
{
   // Fields, properties, methods and events go here...
}

class キーワードは、アクセス レベルの後に配置します。 この例では、public が使用されているため、誰でもこのクラスのインスタンスを作成できます。 class キーワードの後にクラスの名前を記述します。 クラスの名前を、有効な C# の識別子名にする必要があります。 定義の残りの部分がクラス本体で、そこで動作とデータを定義します。 クラスのフィールド、プロパティ、メソッド、およびイベントは クラス メンバー と総称されます。

オブジェクトの作成

クラスとオブジェクトは、同義的に使用されることがありますが、これらは異なるものです。 クラスはオブジェクトの型を定義しますが、オブジェクト自体ではありません。 オブジェクトは、クラスに基づく具体的なエンティティであり、クラスのインスタンスと呼ばれることもあります。

オブジェクトを作成するには、次のように、new キーワードの後にオブジェクトの基になるクラスの名前を指定します。

Customer object1 = new Customer();

クラスのインスタンスを作成すると、そのオブジェクトへの参照が返されます。 前の例の object1 は、Customer に基づくオブジェクトへの参照です。 この参照は、新しいオブジェクトを参照しますが、オブジェクト データ自体を含みません。 実際、オブジェクト参照は、オブジェクトを作成しなくても作成できます。

 Customer object2;

上のような、オブジェクトを参照しないオブジェクト参照を作成するのはお勧めしません。実行時にこのような参照を通じてオブジェクトへのアクセスを試みると失敗するからです。 ただし、新しいオブジェクトを作成するか、既存のオブジェクトを割り当てると、このような参照でオブジェクトを参照できるようになります。次に例を示します。

Customer object3 = new Customer();
Customer object4 = object3;

上のコードでは、同じオブジェクトを参照する 2 つのオブジェクト参照が作成されます。 そのため、object3 を通じて行われたオブジェクトの変更は、後で object4 を使用するときに反映されます。 これは、クラスに基づくオブジェクトが参照によって参照されるからです。このためクラスは参照型と呼ばれています。

クラスの継承

クラスは、オブジェクト指向プログラミングの基本的な特性である "継承" を完全にサポートします。 クラスを作成するときは、sealed として定義されているものを除く、他のすべてのクラスから継承できます。また、作成したクラスから他のクラスを継承し、クラスの仮想メソッドをオーバーライドすることもできます。 さらに、1 つまたは複数のインターフェイスを実装できます。

継承は、派生 を使用して行われます。派生とは、データの動作の継承元である 基底クラス を使用してクラスを宣言することを意味します。 基底クラスは、派生クラス名の後に、コロンと基底クラス名を追加して指定します。次に例を示します。

public class Manager : Employee
{
    // Employee fields, properties, methods and events are inherited
    // New Manager fields, properties, methods and events go here...
}

クラスで基底クラスを宣言している場合、基底クラスのすべてのメンバー (コンストラクター以外) が継承されます。 詳細については、「継承」を参照してください。

C# のクラスは 1 つの基底クラスから直接継承することしかできません。 ただし、基底クラス自体が別のクラスを継承している場合があるため、1 つのクラスに複数の基底クラスが間接的に継承されることもあります。 さらに、クラスは 1 つまたは複数のインターフェイスを直接実装できます。 詳細については、「インターフェイス」を参照してください。

クラスは abstract として宣言できます。 抽象クラスには、シグネチャ定義が存在し、実装は存在しない抽象メソッドが含まれています。 抽象クラスはインスタンス化できません。 抽象クラスを使用するには、抽象メソッドを実装する派生クラスを介する必要があります。 これとは対照的に、シール クラスは、他のクラスに派生させることはできません。 詳細については、「抽象クラスとシール クラス、およびクラス メンバー」を参照してください。

クラス定義は、別々のソース ファイルに分割できます。 詳細については、「部分クラスと部分メソッド」を参照してください。

次の例では、自動実装プロパティ、メソッド、およびコンストラクターという特殊なメソッドをそれぞれ 1 つずつ含むパブリック クラスを定義しています。 詳しくは、プロパティメソッド、およびコンストラクターに関する記事を参照してください。 このクラスのインスタンスは、new キーワードによってインスタンス化されます。

using System;

public class Person
{
    // Constructor that takes no arguments:
    public Person()
    {
        Name = "unknown";
    }

    // Constructor that takes one argument:
    public Person(string name)
    {
        Name = name;
    }

    // Auto-implemented readonly property:
    public string Name { get; }

    // Method that overrides the base class (System.Object) implementation.
    public override string ToString()
    {
        return Name;
    }
}
class TestPerson
{
    static void Main()
    {
        // Call the constructor that has no parameters.
        var person1 = new Person();
        Console.WriteLine(person1.Name);

        // Call the constructor that has one parameter.
        var person2 = new Person("Sarah Jones");
        Console.WriteLine(person2.Name);
        // Get the string representation of the person2 instance.
        Console.WriteLine(person2);
    }
}
// Output:
// unknown
// Sarah Jones
// Sarah Jones

C# 言語仕様

詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。