C# のクラス、構造体、レコードの概要
C# では、型 (クラス、構造体、またはレコード) の定義は、型の動作を指定する設計図に似ています。 オブジェクトは基本的に、設計図に従って割り当てられて構成されたメモリのブロックです。 この記事では、これらの設計図の概要とそれぞれの特徴について説明します。 このシリーズの次の記事では、オブジェクトについて説明します。
カプセル化
"カプセル化" は、オブジェクト指向プログラミングの原理と言われることもあります。 クラスまたは構造体では、クラスや構造体の外部のコードに対して各メンバーがどの程度アクセスできるかを指定できます。 クラスやアセンブリの外部から使用することを意図されていないメソッドや変数は、非表示にして、コーディング エラーや悪用が発生する可能性を軽減できます。 詳細については、「オブジェクト指向プログラミング」のチュートリアルを参照してください。
メンバー
型の "メンバー" には、すべてのメソッド、フィールド、定数、プロパティ、およびイベントが含まれます。 C# にはグローバル変数やグローバル メソッドはありません (言語によっては、グローバル変数やグローバル メソッドが存在する場合もあります)。 プログラムのエントリ ポイントである Main
メソッドも、クラスまたは構造体の中で宣言する必要があります (最上位レベルのステートメントを使用する場合は暗黙的に)。
クラス、構造体、またはレコードで宣言できるすべてのメンバーの種類を次に示します。
- フィールド
- 定数
- Properties
- メソッド
- コンストラクター
- イベント
- ファイナライザー
- インデクサー
- 演算子
- 入れ子にされた型
詳細については、「メンバー」を参照してください。
ユーザー補助
メソッドやプロパティの中には、クラスまたは構造体の外部にあるコード ("クライアント コード" と呼ばれます) から呼び出されたりアクセスされたりするように用意されているものがあります。 その他のメソッドやプロパティは、クラスまたは構造体それ自体でのみ使用されるようになっています。 意図したクライアント コードだけがアクセスできるように、コードのアクセス可能性を制限することが重要です。 型やメンバーがクライアント コードにアクセスする方法を指定するには、次のアクセス修飾子を使用します。
既定のアクセシビリティは private
です。
継承
クラスでは、継承の概念がサポートされます (構造体ではサポートされません)。 他のクラス ("基底クラス") から派生するクラスには、コンストラクターとファイナライザーを除く基底クラスのすべてのパブリック メンバー、プロテクト メンバー、および内部メンバーが自動的に含まれます。
クラスは、abstract として宣言することもできます。このようなクラスは、1 つ以上のメソッドの実装を持っていないことを意味します。 抽象クラスを直接インスタンス化することはできませんが、他のクラスの基底クラスとして抽象クラスを使用し、不足している実装を提供することができます。 また、クラスを sealed として宣言して、他のクラスがそのクラスを継承しないようにすることもできます。
詳細については、「継承」および「ポリモーフィズム」を参照してください。
インターフェイス
クラス、構造体、およびレコードでは、複数のインターフェイスを実装できます。 インターフェイスから実装するということは、インターフェイスで定義されたすべてのメソッドが型によって実装されることを意味します。 詳細については、「インターフェイス」を参照してください。
ジェネリック型
クラス、構造体、およびレコードは、1 つ以上の型パラメーターを指定して定義できます。 クライアント コードでは、型のインスタンスの作成時に型を指定します。 たとえば、System.Collections.Generic 名前空間の List<T> クラスは、1 つの型パラメーターを使用して定義されています。 クライアント コードでは、List<string>
または List<int>
のインスタンスを作成して、リストに保持する型を指定します。 詳細については、「ジェネリック」を参照してください。
静的な型
クラス (ただし、構造体やレコードではありません) は、static
として宣言できます。 静的クラスに含めることができるのは静的メンバーだけであり、new
キーワードでインスタンス化することはできません。 プログラムが読み込まれると、クラスの 1 つのコピーがメモリに読み込まれます。そのメンバーには、クラス名を使用してアクセスします。 クラス、構造体、およびレコードには、静的メンバーを含めることができます。 詳細については、「静的クラスと静的クラス メンバー」を参照してください。
入れ子にされた型
クラス、構造体、またはレコードは別のクラス、構造体、またはレコードで入れ子にすることができます。 詳細については、「入れ子にされた型」を参照してください。
部分型
クラス、構造体、またはメソッドの一部を 1 つのコード ファイルに定義し、別の部分を他のコード ファイルに定義することができます。 詳細については、「部分クラスと部分メソッド」を参照してください。
オブジェクト初期化子
値をそのプロパティに代入して、クラス オブジェクトまたは構造体オブジェクト、およびオブジェクトのコレクションのインスタンス化と初期化を行うことができます。 詳細については、「オブジェクト初期化子を使用してオブジェクトを初期化する方法」を参照してください。
匿名型
名前付きクラスの作成が不便である、または不要である場合は、匿名型を使用します。 匿名型は、その名前付きのデータ メンバーによって定義されます。 詳細については、「匿名型」を参照してください。
拡張メソッド
別の型を作成することによって、派生クラスを作成せずにクラスを "拡張" できます。 その型には、元の型に属しているかのように呼び出すことができるメソッドが含まれています。 詳細については、「拡張メソッド」を参照してください。
暗黙的に型指定されるローカル変数
クラスや構造体のメソッド内では、暗黙の型指定を使用して、コンパイル時に変数の型を判断するようにコンパイラに指示できます。 詳細については、「var (C# リファレンス)」を参照してください。
レコード
C# 9 では、クラスまたは構造体の代わりに作成できる参照型である record
型が導入されています。 レコードは、不変の型でデータをカプセル化するための組み込みのビヘイビアーを持つクラスです。 C# 10 では、record struct
値の型が導入されています。 レコード (record class
または record struct
) には次の機能があります。
- 不変プロパティを持つ参照型を作成するための簡潔な構文。
- 値の等価性。 レコード型の 2 つの変数は、同じ型を持つ場合は等しく、すべてのフィールドに対して両方のレコードの値が等しい場合は等しくなります。 クラスは参照の等価性を使用します。クラスの型の 2 つの変数が同じオブジェクトを参照している場合、これらは等しくなります。
- 非破壊変異の簡潔な構文。
with
式を使用すると、新しいレコード インスタンスを作成できます。これは既存のインスタンスのコピーですが、指定したプロパティ値が変更されています。 - 表示用の組み込みの書式設定。
ToString
メソッドを使用すると、レコードの型名と、パブリック プロパティの名前と値が出力されます。 - レコードのクラスでの継承階層のサポート。 レコードのクラスは、継承をサポートします。 レコードの構造体は、継承をサポートしません。
詳細は、レコードに関するページ参照してください。
C# 言語仕様
詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。