『スラスラわかるC#』補足資料1 読書メモ

スラスラわかるC# (Beginner’s Best Guide to Programmin)

型情報

クラス名やメンバ名等の情報をメタデータ(型情報)と呼び、プログラムの実行時にメタデータを取り出すための機能をリフレクション(reflection)と呼ぶ。リフレクションで得られる型情報のことを実行時型情報(Runtime Type Information)と呼ぶことがある。

実行時型情報

リフレクションを使用することで、文字列から動的にインスタンスを生成することができる。ただし、リフレクションを使った処理は、通常の処理に比べると数千倍ほど遅いため、注意が必要。

属性

属性(attribute)とは、クラスやメンバーに追加の実行時情報を与えるものである。属性の情報は以下のような場面で使われる。

  • 条件コンパイルなどの、コンパイラへの指示に使う(Conditional, Obsolete)
  • 作者情報などをメタデータとしてプログラムに埋め込む(AssemblyTitle)
  • リフレクションを利用して、プログラム実行時に属性情報を取り出して利用する

以下のコード例では、Conditional属性を使用している。SHOW_INTERMEDIATEというシンボルが定義されているときはInterMediateOutputメソッドが実行される。

式ツリー

ラムダ式をExpression型の変数に代入すると、式ツリーデータとして扱うことができる。式ツリーデータとして扱えるのは単文のみ。

式ツリーは、Compileメソッドを呼び出すことで動的にコンパイルして実行することができる。

動的変数

C#4.0で、動的型付け変数(dynamic型)が追加された。

C#のdynamicは、「型が動的」というよりは、「静的な型に対する動的コード生成」といったほうが正しい。

リフレクションやdynamic型は「補足資料」の位置づけでも良いと思うけど、属性はC#でアプリケーションを書くなら絶対に知っておく必要がある事項なので、補足資料に回されてしまっているのは疑問。

『スラスラわかるC#』読書メモ 第11章

スラスラわかるC# (Beginner’s Best Guide to Programmin)

マルチスレッド処理

一本道でしか処理できない状態を同期(synchronous)、複数の処理を平行して行える(ある処理の実行中に別の処理を止めない)状態を非同期(asynchronous)という。

処理を動かすための基本単位のことをスレッド(thread)と呼ぶ。処理の流れが一本道なものをシングルスレッド、複数の処理を平行して行うものをマルチスレッドと呼ぶ。

C#で非同期処理を行う場合、スレッドを直接作ることはほとんどない(System.Threading.Threadを使えば直接スレッドを作ることは可能)。

スレッドの新規作成やスレッド間の処理の切り替えは重たい処理なので、最小限に抑える必要がある。そこで、スレッドを直接使うのではなく、一度作ったスレッドを可能な限り使いまわす仕組み(スレッドプール)がある。

.NET Framework 4.0以降では、System.Threading.Tasks.TaskクラスやSystem.Threading.Tasks.Parallelクラスを使うことで、スレッドプールを簡単に利用することができる。

排他制御

マルチスレッドプログラミングで、別スレッドの実行結果を再利用するような場合には、別スレッドの処理中は処理を止める排他制御が必要になる。C#では、lockステートメントを用いることで簡単に排他制御を行うことができる。

volatile

コンパイラは最適化の過程で無駄な変数等を削除する。しかし、マルチスレッドプログラミングでは、一見無駄に見えても、他のスレッドで値が更新される変数を用意することがある。このような変数には、volatile修飾子を付けると、コンパイラによる最適化で変数が削除されることがない。

非同期メソッド

C#5.0以上では、asyncキーワードを使うことでメソッドを非同期メソッドとして定義できる。awaitキーワードの箇所で非同期処理の完了待ちが行われる。

『スラスラわかるC#』第10章 読書メモ

スラスラわかるC# (Beginner’s Best Guide to Programmin)

列挙子

C#における反復では、列挙可能(Enumerable)及び列挙子(Enumerator)が中心的な役割を持つ。

IEnumerableインターフェースを実装したメソッドは、foreachで反復処理することができる。IEnumeratorインターフェースは、IEnumerableを実装したオブジェクトを返す必要がある。

yield returnステートメントを使うことで、列挙子を簡単に生成することができる。yield returnステートメントは遅延評価される。

LINQ

SQLに類似したキーワードを使用して、データの反復と抽出を行える。クエリ式とメソッド形式の2種類の書き方がある。

『スラスラわかるC#』第9章 読書メモ

スラスラわかるC# (Beginner’s Best Guide to Programmin)

ジェネリック

ジェネリックを使うことで、メソッドを任意の型に対応させることができる。

上記コードで、Tの部分には任意の型が入る。Max(1,2)ならint、Max(1.1, 2.1)ならdoubleで演算が行われる。whereで、Tの型にIComparebleを実装しているという制約を加えている。また、ジェネリックを使うと演算子を利用できなくなるため、比較にはIComparebleで実装が保証されているCompareメソッドを使用している。

ジェネリックなクラスは以下のように定義し、利用する。

defaultキーワード

default(Type)はTypeが数値型の場合は0、参照型の場合はnullを返す。

共変性と反変性

C#4.0以上では、ジェネリックの型のパラメータに共変性・反変性を持たせることができる。

正直言って、この本だけだと共変性と反変性はよく理解できなかった。MSDNのジェネリックの共変性と反変性の方が、コード例が豊富でわかりやすい。

共変性は指定された型と、その派生元の型を使用できること。反変性は、指定された型と、その派生型を使用できること。指定された型のみが使用できる場合は不変性という。

正直言って、まだちゃんと理解できているとはいいがたい。もう少し実例を通して学んでいきたい。

『スラスラわかるC#』第8章 読書メモ

スラスラわかるC# (Beginner’s Best Guide to Programmin)

スタックとヒープによるメモリ管理

.NET Framework向けのプログラミング言語で書かれたプログラムは、管理されたコード(managed code)と呼ばれる。マネージドコードはメモリやセキュリティが管理されている。

スタック

スタックはLIFO(Last In First Out)でデータを管理する。値型のインスタンスに使われる。スタックによる領域の確保と解放は、スコープの出入りのタイミングで行われる。

ヒープ

ヒープは任意サイズのデータ量を任意の順序で確保・解放する。参照型のインスタンスに使われる。スタックとヒープを比較すると、スタックのほうが効率的であることが多い。スタックの制限内で特に問題のないデータに対しては、可能な限りスタックを利用すべき。

領域の確保と解放を繰り返すことで、使用中のヒープがメモリ上に散在する状態ができる断片化(fragmentation)の問題もある。

ガベージコレクション

C#では、ヒープ領域はガベージコレクションによって自動的に解放される。

値型と参照型

データのサイズが小さく、継承の必要のないものは値型として定義し、それ以外のものは参照型として定義する。

C#の型の分類

値型;構造体型(ユーザー定義構造体、数値、真偽値型)、列挙型
参照型;クラス、インターフェース、デリゲート、object、文字列、配列

ボックス化

値型のインスタンスをobject型の変数に代入することをボックス化という。ボックス化はできるだけ利用しないことが望ましい。

引数の参照渡し

メソッドの引数にrefキーワードをつけることで、参照渡しにできる。

out修飾子による出力引数」

メソッドで複数の熱尾を返したい場合、C#では、参照渡しではなく出力引数(out修飾子)を使うことができる。out修飾子を使えば、メソッド内で変数を初期化することができる。

Null許容型

通常、値型はnull値を取ることができない。C#にはNullable型という特殊な型があり、この型は値型でありながらnull値をとることができる。

Null許容型の定義は、値型の型名の後ろに?をつける。

Nullable型にはHasValueとValueというメンバーがあり、HasValueは値がnullならばfalseを返す。

Nullable型に対する演算の規則は何種類かあるが、たとえば 1 + null はnullになる。

?? 演算子を使うことで、値がnullか判別し、nullの場合には別の値を割り当てることができる。

リソースの破棄

ファイルのように、ガベージコレクションの管理対象外のリソースのことを、非管理リソース(Unmanaged Resource)と呼ぶ。
ファイルリソースを読み込む際は、適切な解放処理を行う必要がある。
通常、ファイルリソースの解放はtry-catch-finallyを使用してfinallyで行われることが多いが、C#では、usingステートメントを使うことで、ファイリソースの解放処理を簡単に書くことができる。

usingステートメントで使うリソース管理用クラスは、System.IDisposableインターフェースを実装している必要がある。