はじめに
この記事は、Exam Ref 70-483『C#でのプログラミング』の試験対策書籍の私的まとめ その1の続編となります。
Ch2. Create and use types
学べるスキル
- 型の作成について(型宣言)
- 型の利用方法
- カプセル化について
- クラス階層の作成と実装方法
- プログラム実行による型探索と型の自動生成
- オブジェクトのライフサイクル管理
- 文字列の扱い
要約
- ソリューション内のオブジェクトは、参照値によって管理できる。構造体
struct
は値の型である。つまり、代入中に構造体の内容(特定の値)が1つの変数から別の変数にコピーされる。クラスclass
は参照型である。つまり、割り当て中に、割り当てられた対象が割り当て先のソースと同じオブジェクトを参照する。 - 不変オブジェクト(immutable objects)とは、名の通り変更できないオブジェクトである。
DateTime
などの不変オブジェクトは新たなオブジェクト(オリジナルの変異コピー、つまりオリジナルと異なる)を提供するために利用できるメソッドを提供する。たとえば、DateTime
構造体は、指定された未来の日数を表す新しいDateTime
構造体を返すために使用できるメソッドを提供する。 - ジェネリック型は、型設計で「プレースホルダー」として使用できるため、型が機能するオブジェクトの型を動的に確立できる。ジェネリック型が使用される状況の良い例は、リスト型と辞書型の作成である。
- 型は、その型の新しいインスタンスが作成されたときに呼び出されるコンストラクターメソッドを指定できる。コンストラクターには、オブジェクトの初期化に使用できるパラメーターを指定できる。コンストラクターが初期化データが不正であるという欠陥がある場合、コンストラクターが完了するとオブジェクトが作成されるため例外をスローして構築プロセスを中断する必要がある。コンストラクタは、指定された型をインスタンス化することができる様々な方法を提供するためにオーバーロードすることができる。
this
構文を使用すると、型の1つのコンストラクターが別のコンストラクターを呼び出して、マスターコンストラクターの作成が許可され、オブジェクトでのコードの重複を回避できる。クラスには、続くクラスの最初のインスタンスが作成されたときに一度呼び出される静的コンストラクターを含めることができる。 - 型には、オブジェクトが動作を実行できるようにするメソッドを含めることができる。メソッドはいくつかのパラメーターを受け入れ、特定のタイプを持つ。
void
型のメソッドは値を返さないが、任意の型のメソッドはその型の結果を返す必要がある。 - 拡張メソッドは、追加先のクラスの機能に追加できる。拡張メソッドは、追加されたクラスのプライベートデータメンバーにはアクセスできない。
- メソッドのパラメーターは、呼び出されたときに名前で識別できる。 これにより、プログラムの可読性が向上し、パラメーターが間違った順序で入力されたためにエラーが発生する可能性も低くなる。
- メソッドのパラメーターは、パラメーターのデフォルト値を指定することによりオプションにすることができる。 パラメータがメソッド呼び出しから除外されている場合は、代わりにデフォルト値が使用される。
- オブジェクトは、返される項目を識別するためのインデックス値(通常は整数)を提供するために使用できるインデックス付きプロパティを提供できる。
- 単一の型のメソッドはオーバーロードできる。 これは、型に同じメソッドの複数のバージョンが含まれ、それぞれが異なる署名を持つことを意味する。メソッドのオーバーロードは、異なるデータ入力から特定のタスクを実行する方法が複数ある状況で使用される。
- クラス階層内のメソッドはオーバーライドできる。 オーバーライドするには、メソッドを
virtual
としてマークする必要がある(仮想メソッド)。階層内のクラスのインスタンスで仮想メソッドが呼び出されると、システムはクラスオブジェクトを指定して、クラスオブジェクトで述べられているメソッドの実装についてクラス階層を検索し、見つかった最初の実装が呼び出される。 メソッドのオーバーライドは、クラス階層内のオブジェクトが特定の方法で特定のアクションを実行できる必要がある場合に使用される。base
キーワードを使用すると、メソッドはオーバーライドされたメソッドを呼び出すことができます。 - アプリケーション内のすべてのアイテムは特定の型
Type
である。C#の型Type
システムは、参照型と値型の間を自動的に変換し、自動的に値を変換(拡大)する。このことでデータが失われない限り、この自動変換は賢明なことである。 - 型変換によりデータが失われる(縮小する)場合、プログラマはキャストを使用して値の変換を明示的に要求する必要がある。
- C#アプリケーションが静的に型付けされていない言語やサービスとやり取りできるように、動的
dynamic
型が提供されている。これにより、型付けの情報がエラーを示している場合でも、オブジェクトの型を無視してプログラムをビルドするようコンパイラーに指示できます。 - 動的型が使用される場合、作成される変数の型は、使用されるもののコンテキストから推測される。これは、コンパイルエラーとして検出されたであろうエラーが、実行時(run-time)エラーに変更されることを意味する。
- 動的型は、コンポーネントオブジェクトモデル(COM)ベースのサービスと対応させるときに特に便利である。動的型は、使用されるものの状況から正しい型に自動的にマッピングできるためである。
- C#アクセス修飾子を使用すると、クラスのメンバーをクラス外のコードから隠すことができる。特に指定しない限り、クラスメンバーはクラスに対してプライベート
private
であり、クラスの外部からはアクセスできない。 データメンバーをパブリックpublic
にすると、クラス内のそのデータメンバーへの制御されないアクセスが許可されるが、これは良い考えではない。 - C#プロパティを使用すると、外部コードがクラスのメンバーとやり取りしたいときに、
get
およびset
動作により制御できる。プロパティは、クラスによって管理されているデータのバッキングフィールド値(a backing value)を保持するクラスのプライベートメンバーへのアクセスを制御できる。プロパティは読み取り専用プロパティのget
動作、および書き込み専用のプロパティのset
動作を提供することができる。get
およびset
動作には異なるアクセス修飾子を設定できるため、プロパティのget
動作をパブリックに、set
動作をプライベートにできる。 - 一般的に、クラスが他のクラスで使用するために公開するメソッドは
public
する必要があり、クラス内に含まれるデータはprivate
にする必要がある。 -
protected
アクセス修飾子により、クラス階層のクラス内でクラスメンバーを参照でき、internal
アクセス修飾子により、クラスメンバーと同じアセンブリ内のコードからクラスメンバーを参照できる。 - インターフェイスの動作を実装するクラスのメソッドは、このインターフェイスを明示的に
explicitly
実装するものとして識別できる。これにより、カプセル化が改善される。これは、これらのメソッドを使用できるコンテキストが、オブジェクトへの参照ではなく、インターフェースへの参照を介することだけであることを意味する。Explicit
実装は、クラスが複数のインターフェイスを実装し、一部のインターフェイスに同じメソッドが表示される場合の混乱の可能性も排除する。 - C#クラスは、インターフェイスに記述されている各メソッドに一致するメソッドセットを含むインターフェイスを実装できる。インターフェイスを実装するクラスは、インターフェイス型の参照によって参照できる。
- C#クラスは、それを拡張する子クラスの基底クラスとして機能することができる。子クラスは、基本クラスのすべてのメンバーを継承し、C#の
override
メカニズムを使用して、子クラスにより固有の動作を持つ基本クラスのメソッドのオーバーライドバージョンを提供する。基底クラスのメソッドをオーバーライドするには、仮想virtual
として宣言する必要があります。 オーバーライドメソッドはbase
キーワードを使用して、基底クラスのオーバーライドされたメソッドを呼び出すことができます。 - プログラマーは、基底クラスのメソッドの代替メソッドを作成できる。 これは推奨されない。
- クラスを封印済み
sealed
として宣言して、子クラスの基礎として使用されないようにすることができる。 基本クラスのメソッドを拡張するクラスのメソッドは、それらがオーバーライドされないように、sealed
されていると宣言することもできる。 - 子クラスを作成するには、プログラムで基底クラスのインスタンスを作成する必要がある。 基底クラスにコンストラクターがある場合、子クラスはこれを呼び出して必要なパラメーターを指定する必要がある。
base
キーワードは、この目的のためにコンストラクターで使用される。 - クラスは抽象
abstract
クラスとして宣言できる。その場合、子クラスに実装されるメソッドの署名が含まれる。抽象クラスはクラスのテンプレートとしてする。 - 基底クラスへの参照は、基底クラスを拡張するクラスから作成されたオブジェクトを参照できる。 ただし、その逆は当てはまらない。 子クラスへの参照を作成して、親のインスタンスを参照することはできない。
- クラスは
IComparable
インターフェイスを実装できる。これは、その型のオブジェクトの順序を決定するために使用できるCompareTo
というメソッドが含まれていることを意味する。IComparable
動作は、List
型で提供されるSort
メソッドなどのメソッドで使用できる。このメソッドはオブジェクトを順番に配置できる。 - クラスは列挙のコンシューマー(
foreach
構造など)がクラスを処理するために使用できる列挙子を提供するメソッドGetEnumerator
を提供するIEnumerable
インターフェイスを実装できる。 -
yield
キーワードは、プログラマーが列挙子を作成する簡単な方法を提供する。列挙のコンシューマーによって列挙から次のアイテムが要求される限り、列挙子メソッドの状態を返し続ける。 - クラスは
IDisposable
インターフェイスを実装できる。 このクラスには、使用している重要なリソースを解放するようにクラスのインスタンスに指示するために呼び出すことができるDispose
メソッドが含まれます。Dispose
メソッドは、ガベージコレクションプロセスによって自動的に呼び出されることはないが、using
構造内でオブジェクトのインスタンスが作成および使用される場合、自動的に呼び出される。 -
IUnknown
インターフェイスは、コンポーネントオブジェクトモデル(COM)オブジェクトと直接対応する必要がある.NETコードを作成するときに使用できる。 - メタデータとは、本体であるデータに関する付帯情報が記載されたデータである。C#プログラムのコンテキストでは、コードのメタデータは、コード要素に関連付けられた1つ以上の属性インスタンスの形式で表現される。 このメタデータは、プログラムのビルド時に作成され、アセンブリのロード時に属性クラスインスタンスにロードされるアセンブリファイルに格納される。
- 属性
Attribute
クラスは、属性クラスを拡張し、"Attribute"というテキストで終わる名前を持つ。属性クラスは空にすることができる。その場合、特定の属性がアイテムに適用されていることを示すだけであるか、属性にプログラムでアクセスできるデータ要素を含めることができる。属性は、プログラム内のさまざまな要素に適用できる。例えば、AttributeUsage
属性を属性宣言に追加して、属性を適用できるオブジェクトとクラスを指定することができる。 - リフレクション
Reflection
を使用すると、プログラムは型の内容を調査し、プログラムで型の情報を反映させることができる。 - リフレクションはアセンブリ内の型の特性を決定できるようにアセンブリ上で使用することができる。これを使用して、コンポーネント(構成要素)ベースのシステムが必要なコンポーネントを自動的に選択してロードできるようにすることが可能。
- プログラムコードは、名前空間、クラス、プロパティ、およびクラスメンバを指定できるCodeDOMドキュメントモデルを使用して、プログラムで生成することができる。 CodeDOMオブジェクトは、バイナリアセンブリファイルまたはC#またはVisual Basicのソースファイルとして出力できます。
- プログラムコードによる動作をプログラムにより生成する別の方法は、実行するアクションを提供するラムダ式と、他のプログラムアクションを指定する一連の式ノードタイプを含むラムダ式ツリーを作成することである。式ツリーは、LINQクエリや動的言語の実装などのプログラムの動作を表現するために使用される。
- オブジェクトのガベージコレクションにより、プログラムの作成がはるかに簡単になる。 C#のガベージコレクションシステムは自動的に実行され、未使用のオブジェクト(参照によって参照されていないオブジェクト)を削除する。
- ガベージコレクションの実行中、アプリケーションスレッドは一時停止する。
- ガベージコレクターは永続オブジェクト(ガベージコレクションの後に存在するオブジェクト)を認識し、それらをガベージコレクションプロセスから除外する。
- ガベージコレクションプロセスは手動で開始して使用できるが、これは推奨されない。
- オブジェクトの削除時に解放する必要があるリソースへの参照を含む未使用のオブジェクトには、ガベージコレクションプロセス中に実行されるファイナライザメソッドを含めることができます。 ファイナライザメソッドは、オブジェクトに割り当てられたリソースを解放できる。
- ファイナライザーメソッドよりも、オブジェクトは
IDisposable
インターフェイスを実装し、アプリケーションがリソースを解放するようにオブジェクトに指示するために使用できるDispose
メソッドを含めることができる。using
ステートメントを使用して、プログラムの一部のみで使用されるオブジェクトでDispose
メソッドが呼び出されるようにすることができる。 -
using
による破棄パターンを用いることで、オブジェクトはfinalizeとDisposeの使用を組み合わせて、オブジェクトが保持しているリソースが正しく解放されるようにすることができる。 - 文字列
string
は、任意の長さの文字char
のコレクションである。 - 文字列変数は不変である(変更できない)が、参照によって管理される。 この組み合わせは、値型として扱うことができることを意味します。
- コンパイル中に、特定の文字列の文字列リテラルの複数のコピーがメモリ内の単一のインスタンスにマッピングされる。 つまり、プログラムが文字列リテラル「cheese」をいくつかの異なる文字列変数に割り当てると、すべての変数が参照するテキスト「cheese」を含む単一の文字列値が作成されるということである。
- 多くの文字列を一緒に追加して大きな文字列を作成すると、多数の部分文字列が作成されることになる。
StringBuilder
型は、変更可能な文字列実装を提供する。プログラムは、StringBuilder
インスタンスの内容を変更できる。StringBuilder
は、大きな文字列を組み立てるより効率的な手段を提供する。 -
StringBuilder
クラスとStringWriter
クラスを使用すると、TextReader
およびTextWriter
Streamで動作するプログラムで文字列を扱える。 - 文字列型は、文字列を操作するためのさまざまなメソッドを提供する。 例えば、文字列内の部分文字列の場所を確立し、それらを抽出して、文字列の開始と終了を一致させることができる。
- 文字列の内容は変更できない(文字列は不変である)が、文字列の置換メソッドを使用して、更新された内容で新しい文字列インスタンスを作成できる。
- 文字列の一致は、文字コードを使用して、または同じ単語の複数のスペルが一致する特定の文化に従って実行できる。
- 文字列は、たとえば
foreach
構造を使用して列挙できる。 - 文字列は
IFormattable
インターフェイスを実装できる。つまり、文字列には、書式設定とカルチャ情報を受け入れる追加のToString
メソッドが含まれる。 - 文字列補間において、プログラムは、文字列リテラル(先頭に$文字が付く)を利用できる。この文字列リテラルは、書式設定情報と、書式設定して文字列に組み込む変数名を組み合わせる。補間された文字列はコンパイル時に処理され、複合形式の文字列が生成される。
関連記事
参考書籍
『Exam Ref 70-483 Programming in C#, 2nd Edition』 By Rob Miles