C#メモ


  • コレクションとジェネリックの関係
通常、ジェネリックは、コレクションおよびコレクションに対して動作するメソッドと共に使用される。
ArrayList などは非ジェネリックの互換性確保用のクラスなので使わないようにすると良い。

  • クラスのコンストラクターに型はいらない
何故なら返り値が存在しないから。考えれば当たり前。
スニペットはctorを選択すると自動生成される。

  • 暗黙的派生
配列は、System.Array クラスから暗黙的に派生します。
System.Int32 (C# のキーワードは int) などの組み込み数値型を含むすべての型は、最終的に System.Object (C# のキーワードは object) という単一の基本型から派生します。
資料:http://msdn.microsoft.com/ja-jp/library/ms173104.aspx
(つまり配列などはforeach等でコレクションとして利用できる、またToString()等で簡単に変換できる)


  • エスケープシーケンス
/は¥マーク(半角)で入力しないとコンパイラーは認識しない(日本語環境の場合)文字列のエスケープ シーケンス
\r\n 改行 備考:TextBoxコンポーネントのマルチラインのtextプロパティ内で改行が行われた場合自動的に「\r\n」となる
尚、エスケープシーケンスを回避して文字列を処理する場合ダブルクオーテーションの前に”@”を付けると良い
@"c:\"

  • 参照変数とオブジェクトの違い

オブジェクト例
Random random = new Random();

参照変数例
Label firstClicked = null;

newが無い場合、オブジェクトは作成されない。参照変数はオブジェクトの追跡(参照)する為だけに使用できる。

  • クラスのフィールド
基礎的なこととしてクラスのフィールド内に書かれた変数はクラスがIDisposeされるまで生きているし、値も保持されている(当たり前のことだがあくまで基礎的な確認として書いておく)

タスクを作成する際に便利。関数へのポインタを作れる

  • is演算子
isはそのオブジェクトが対象となるオブジェクトから派生したか調べることが出来る
例:if (formatProvider is CultureInfo)

  • C# 「型の宣言」と「型の定義」はどう違うのか?
C++では明確に違いがあったがC#においては希薄になっているようだ。abstruct や delegate などによって「宣言」の存在意義が消滅してる?

IList, ICollection, IEnumerable, ICloneable等様々な機能のクラスを継承していて配列として扱えます。
ArrayList.Sort メソッド (System.Collections)等の機能も提供されています。(資料
より基底にはArray クラス (System)がある。

2 つのオブジェクトを比較するメソッドを公開します。継承したクラスのメソッドCompare()に比較する仕組みを書いてsort()にクラスを引数で渡します。
IComparerはSystem.Collections名前空間
IComparableはSystem名前空間
にそれぞれ所属しています。

IComparable.CompareToはsort()時の判断基準を提供する。CompareTo関数からの返値が
「0」の場合は同一として処理する。
「-1」の場合は順番通りとして扱い、そのまま。
「1」の場合は逆順になっていると判断して前後をすりかえる。

  • IEnumerable と IEnumerator は一組で機能する(資料

IEnumerableを継承した自作クラスはforeach反復処理を可能とする。

Current、MoveNext、Resetで構成されたインターフェイスクラス。実装することにより要素を1個ずつ列挙する機能を提供する。

抽象メソッド(interfaceの定義部分)は規約のみを定め、実装はその派生クラスで行うことになる(外部仕様と内部実装の関係にある)
インターフェイスクラス等は外装みたいなもので実体は無い(実際に値や参照を持つわけで無い)(資料2
インターフェイスクラスは頭文字がIで始まる。例:IList、IComparer等
クラスのインスタンスからアクセス → NG
インターフェイスを継承したクラスのインスタンスからインターフェースのクラスにアップキャストしてアクセス
→ インターフェイスクラス内で定義されたプロパティ、インデクサ、イベント、メソッドが利用できる(もちろんだが継承したクラス側できちんと実装されている必要がある)
(機能的な関係はabstractとoverrideに似ている。派生クラスで実装され、基底であるインターフェイスクラスからアクセスする)
インターフェイスクラスを導入するとabstractとoverrideで各クラスの関係を書かなくてもすむ(コードがみやすく簡潔に書ける)又、インターフェイスクラスは複数同時に継承できる点が異なる
基本的な指針として「機能性を継承するときは継承を使い、呼び出し方法を合わせるときはインターフェイスを使う」のが良いようだ。

  • C#の配列
C#で作成された配列は全て自動的にSystem.Arrayクラスを継承します。
System.ArrayクラスはIComparable インターフェイスを使って順列方法を指定してソートを行こなったりすることが出来ます。

ソート方法などを指定するメソッドが含まれたインターフェイスクラス。CompareToメソッドなどはうまく使うと便利なので活用すると良い。

  • foreachの特徴
例:foreach( int n in ar ){Console.WriteLine( n );} の場合、nに値、arは配列要素で上限まで繰り返し処理される。
配列にはIEnumerableというインターフェイスの実装が実装されている必要がある。標準的な数値型(int等)はすでに実装されている。
アクセス専用、配列の内容を書き換えられないことに注意。

staticキーワードをつけると静的メンバーになる。staticを付けた変数は、プログラムのなかに実体が1個しか作られない。
静的変数・静的関数は「クラスごとに唯一つの実体を持ち」すべてのインスタンスの間で共有される(その機能上、クラス変数/関数と呼ぶ場合もある)
「すべてのインスタンスの間で共有される」という事はstatic修飾子が付いたクラス内部の関数はインスタンスを作成しなくても外部から直接起動できる事を意味する。
ちなみに、通常のメンバー変数/関数は、インスタンス変数/関数と呼びます。

  • C#のイベント機能
C#ではイベント処理の機能が内蔵されている。delegate型の定義、ターゲットとなるハンドラー関数の定義、これら各要素のシグネチャをあわせて用意し
event型変数にデレゲートをセット。event型変数に+=等でイベントをスタック。
イベントから戻ってくる際に必要な「呼び出しを行ったクラスのポインタ」を用意してevent変数からハンドラーを実行する。
利用するにはこの5つの工程が必要。イベント呼び出しには制限がありイベントが記述されたクラス内からしか行うことができなくなってる(継承されたクラスもNGなので注意)
ハンドラー実行時に渡す第二引数はEventArgsを継承したクラスである必要がある(資料

  • ハンドラ
ハンドラとはイベントが呼び出されたときに実際に処理されるコードのことである。
これは通常のメソッドとして記述される。デレゲート型で定義されたものとシグネチャ(引数、戻り値)をあわせておく必要がある。

インデクサを定義することでユーザー定義型のインスタンスに配列と同様なインデックスを付けることができます。
配列化したプロパティみたいなもの。インデクサのアクセサはパラメータを受け取る点が異なる
基本的にインデックスとセット及びゲットできるデータは一対一であることに注意(valueがひとつしか値をもてないので複数の引数が必要な関数を利用する場合等、インデクサを利用できない)

  • インデクサ2
C#において string(文字列)と char[](文字の配列) は同じではない。
前者は System.String (stringクラスのメンバーを利用できる)、後者は System.Char[] (arrayクラスのメンバーを利用できる)になる。
つまり全く別個のデータ型(クラス)になっている。

  • インデクサの自作
IndexClass t = new IndexClass();
Console.WriteLine( t[2] );
t[0] = 'X';
等のようにインデクサでアクセスできるクラスを作成できる。(作成方法のサンプル)
これらの作成には基本的にアクセサが利用される。インデクサが配列であるかのようにアクセスできる機能とすれば、プロパティはメンバ変数であるかのように記述できる手段を提供する機能である。

アクセサ(accessor)とはクラスのカプセル化の為、private化したメンバー変数の値の取得・変更を行うための関数のことを指す。
(プライベートフィールドというのがミソ。これで外部から直接アクセスできなくなっている(見えなくなってる)従って関数経由以外で変更できなくなっている(プロパティを設定する事で外部から見えるようになる)
プロパティとはクラス内部から見るとメソッドのように振る舞い、 クラス利用側から見るとメンバー変数のように振舞うものを指す。
C#では「getプロパティアクセサ」、「setアクセサ」、「valueパラメータ」「return ステートメント」を利用できます。
getはreturnで値を返すようにメソッドを作成します。setはvalueを利用して値を割り当てるようにメソッドを作成します。暗黙の value は、アクセサの設定およびイベント ハンドラの追加と削除に使用されます。
set メソッドが実装されないプロパティは読み取り専用につくれる。(同時にジェネリック型と使用を組み合わせることにより型に依存しないインターフェイスのようなものが作れるっぽい?)
<例>
           public T Element
           {
               get { return this.element; }
               set { this.element = value; }
           }

  • コレクション
IEnumerable インターフェイス

分業などに便利。コンポーネント指向に組める仕組み。
分業などで各人がそれぞれの名前空間を作り関数やクラスなどを作ると名前が衝突する事が無くなる。
名前空間名はネストできる。
namespace Space1.Sub1

namespace Space2
{
   namespace Sub1
   {...

これらを呼ぶときなどは「Space1.Sub1.Class1.test();」とする。


<定義>
   class Class1
   {
       public string hello;
   }
<実装>
           Class1 c = new Class1();
           c.hello = "Hello!";
           object o = (object)c;  //ここでobject型にしている。これをボクシングと呼ぶ。ボクシングで情報が欠落することはない。
           Class1 c2 = (Class1)o;  //ここでobject型からClass1型へ型変換しているがこれをアンボクシングと言う
           Console.WriteLine("{0},{1}",c.hello,c2.hello);
<結果>
Hello!,Hello!
このように参照型は、object型などのより基本的な型にキャストしても、元の型に再キャストすれば、完全に元どおりの機能を取り戻す。
派生クラスから基底クラスに代入できるのと同じ仕組みで、派生から基底に再キャストもOKという事がこれで確認できる<資料
参照と違って整数型(int等)の値型の場合、キャストによってデータが失われたら永遠に戻らない(ちなみにo.helloをアクセスしようとしても無理)

  • 定数値にキャスト
定数の語尾にキャストする型を書ける。
尚、符号付きと符号なしのデータ型は違うものだと認識して混用はなるべく避ける方がよい(扱うビット数が同じでもキャスト変換時符号の関係で数値がおかしくなる)
また実数型から整数型に変換させることは可能だがこの際、四捨五入でなく小数点部分が斬り捨てられる(1.75→1 1.25→1 0.75→0 -0.75→0 -1.75→-1)
例:decimal e = 0.123456789m;
u 符号なし
l long型
f float型
d double型
m decimal型

intやstruct等の値型 インスタンスは内包しているので必要ない。宣言後即利用可
classなどの参照型 インスタンスの作成などは利用者側がしなければならない。参照用の変数とnewして作成したインスタンスのセットが基本
object等の汎用クラス型 classの親戚なので基本参照だがインスタンスの作成まで自動で行っているので注意。値を代入するだけでもその都度みえないところでインスタンスを作成している

structは構造体。構造体は値型、クラスは参照型。classはstructに出来ないことができる。(詳細参照
Structs型の変数は、それ自身がインスタンスを中に持っているようなものなので、改めてnewを用いる必要はない。
もし、構造体にコンストラクタのコードを書いたら「構造体に明示的なパラメータのないコンストラクタを含めることはできません。」とコンパイラに怒られる。
(structでも引数を与える初期化用メンバー関数なら作成可能でこれを構造体のコンストラクタがわりとして扱う事は可能(newする際に引数を与えてインスタンスを直接作れる。このnewは必須でない?))
また、struct内でポリモーフィズムを利用したメンバー関数のコードを書くと「コントロールが呼び出し元に返される前に割り当てられている必要があります。」等のエラーが出る。
クラス 構造体
型の分類 参照型 値型
インスタンス 必須 インスタンスを作成しなくても自身が持っている
継承 できる できない
多態性(ポリモーフィズム) 使える 使えない
コンストラクタ 使える 使えない
メンバー変数、メンバー関数 使える 使える

基底クラスobjectを利用するとobject型にどんなデータの型でも参照を格納できる(整数、実数、文字列、Structs、クラス)
この機能をボクシングと呼ぶ。この機能はある程度の処理速度を食う。非常に便利な機能だが速度が欲しい部分では注意が必要(しかしかなり便利な機能なのでよく考えるべき)

値型 struct 変数に直接値が格納される(情報を引き渡すときに情報をコピーする) 型のサイズが大きい場合複製コストが大きい。読み書きは高速 newしなくても使える(インスタンスは必須ではない)
参照型 class ポインタが格納される 間接参照が生じるので値の読み書きは値型にくらべ低速 newする必要がある(インスタンスが必ず必要)
情報を渡すときにコピーする=小さなデータなら問題ないが巨大なデータでは処理速度が低下する。しかし個々のデータが十分に小さいとデータの場所(ポインタ)を渡すより素早い。
つまり struct はある程度小さなデータの集合でないと非能率になる。反対に class の場合、小さなオブジェクトからなる巨大な配列を使用するような処理を効率的に行うのが困難である<参考資料
またclassはnewしてメモリを確保するがこの時の処理は非常に重い(特にループ内でnewするなどは最悪)。反対にstructはnewしなくても直接使える。
(実行時にプログラム中で動的にメモリを確保するのとコンパイル時に決まった容量をあらかじめ確保しておく仕組みの違いもある)
複数の参照型の変数で同一の値を参照した場合(エイリアスを作った場合)全てのエイリアスの値はget時もset時も同一の値となる(ポインタ参照だから当然の結果)

基底クラス 派生クラス
スーパークラス サブクラス

オーバーロードもあわせて参照すると良い。要約するとnew、virtual、override、abstruct等の機能を利用する事。

基底クラスのメソッドと同名の派生クラスのメソッドをnewで作成すると、インスタンスの型により基底/派生のどちらかのメソッドが呼び出されるようになります。
(ちなみにこのnewは省略してもかまわないが、ソースコード的に派生/基底内に同名メソッドがあると判りにくいので「クラスの利用者」のことを考えて付ける方がよいと思う)
基底/派生両方の関数が生きているのがオーバーライドとは違う。

基底クラスで宣言されていたvirtual修飾子の関数を、派生クラスのoverride修飾した同名関数で上書きする事をオーバライドするという。
上書きされた基底クラスのメソッドは消失する。基底クラスのメンバーを流用しながら派生で変更が必要なメソッドを書き換え使い分ける感じで利用する。
ちなみにオーバーライドされたものより仮想メソッドでnewしたものの方がコンパイル結果は最適化されやすい。そのため特に必要とされない限り、virtualキーワードは使わないのが普通。

純仮想関数(抽象関数)abstractを含んだクラスは抽象クラスとなり派生クラスの継承と関数のオーバライドを必ず要求する。
abstractした関数は中身が必要ない。<注意>abstractを含んだクラスはabstract修飾子が必要になる。省略不可。
抽象クラスのインスタンス化は禁止され派生クラスを作る事でしかそのクラスは利用できなる。
インスタンスを作ろうとすると「抽象クラスまたはインターフェイス~のインスタンスを作成できません」とコンパイラから怒られる。
IEnumerator などの内部は abstract が含まれているので派生させて純仮想関数をオーバーライドする必要がある。
この純仮想関数機能はクラスを運営する上で必ず実装させなければならない機能、関数を要求する場合に利用するようだ?

  • オーバーロード
同じメソッド名でありながら「与える引数」によって複数種類の動作を切り替え行う関数のことをオーバーロードしたメソッドという。
つまり関数の名前が同じで引数リストだけが異なる関数を複数作ることが出来ます。
オーバライドと語感がよく似ているが違うので注意。(実装の仕方はここを参照

  • CとC#の配列の違い(マネージ配列)
Cでは配列は一種の構造体でしたがC#では配列は参照型のオブジェクトになっている。

コレクション(コンテナ)とは配列やリスト、辞書などの複数の要素をひとつにまとめるクラスのことです。
データー格納方式には用途により様々ありますが要素を統一した共通のインターフェースで扱うようにC#ではIEnumerable等のクラスが用意されています。
これらを実装すればforeachで、すべての要素を簡潔に読み出すことが可能となりコレクションの管理や操作が行いやすくなります。

エラーが起きたときの処理を例外処理としてtry、catch、finaly等を利用してコードに書く。
例えば目当てのファイルの読み込みでファイルが存在しなかったり、ユーザーからの入力が期待したものでなかった場合などの処理を行う際に便利である。

型をパラメータとして与えて、その型に対応したクラスや関数を生成する機能(「どんな型」でも入る「型」として使える)
メソッドやクラス名の後ろに< > で囲って型をパラメータとして与えることができます(大抵、「T」や「Type」等と書いていることが多いが基本<>で囲んだワードがそれをあらわす。この部分を型引数と呼ぶ)
例:public Type TestMethod<Type>(Type x,Type y){...}
例:public class<Type>{...}
ただし利用するとボクシングが発生するので処理速度が欲しい部分ではあまり使わない方が良いらしい?(未確認)詳しくはボクシングを参照。

ある特定のメモリ空間や変数に対して、複数の変数からアクセスできる場合、それらの変数をエイリアスと呼びます。

演算子は operator キーワードを用いることでクラスの静的メソッドとして定義することが出来る。定義は必ず publicでstaticにする必要がある。

コンストラクタに引数が設定されていた場合、newする際に引数を渡す必要がある。純粋なコンストラクターメソッドに返り値は必要ない(voidもいらない)。オーバーロード可。
コンストラクタ内でthisキーワードを使うとクラス自身の位置からメンバーにアクセスできる。thisは派生、baseは基底
デストラクターでのメモリの開放はC#が制御を行うので何時開放されるか明確でない。
プログラマ側が明確に開放を指定するにはusingを利用した方法を使う。

  • クラス、派生の特徴(参照
派生クラスのインスタンスが作成された際は、その派生クラスの基底クラスのコンストラクタも同時に起動される。
基底クラスで定義されたメンバーを派生クラスの同名メンバーで隠蔽できる。これを基底クラスのメンバーの隠蔽と呼ぶ。
これは隠れているだけで実装自体は存在する(上書きされるわけではない)ので、たとえば派生に基底クラスのキャストを与えて呼び出すことが可能。例:((Base)d).Test();
また、クラス宣言時「sealed」修飾子をつけるとそのクラスは継承が禁止される。

  • 修飾子
アクセスレベルを修飾子で設定する。メンバー宣言時、修飾子を省略するとprivateになる。
public protected private
クラス内
派生クラスからアクセス ×
外部からアクセス(インスタンスからアクセス等) × ×

構造体やクラス中の呼び方
関数 メンバー関数 メソッド
変数 メンバー変数 フィールド

procedure:プログラムの動作の手順のこと

  • 注釈
/// <summary>
/// オブジェクトの要約。
/// </summary>
/// <value>
/// プロパティの説明。
/// </value>
該当するメンバーの直前に以上のように<summary>や <value>で囲んだ注釈を書くとマウスカーソルを合わせたときヘルプを表示できる(ビジュアルスタジオのこのような機能をインテリセンスと呼ぶ)

C# では、基底クラスを指定せずに作成した型は全て自動的に object 型を継承することになります。
(構造体等の値型は明示的に他の型を継承できないので、必ず object を継承します。) つまり、C# における全ての型は object の派生クラスになります。

  • シグネチャ
(戻り値、引数)の事。デリゲート宣言などでは呼び出すメソッドとシグネチャ(戻り値、引数)をあわせる必要がある。

  • 派生クラスの作成時の注意点
派生クラスを作成する際は基底クラスのコンストラクタに注意。ここで引数が必要な基底コンストラクタを作成すると派生クラスのインスタンス生成時、
基底クラスのコンストラクタも呼び出されるがその際引数なしのコンストラクタになってしまう。
その為、以下のように自分でコードを書いて基底「base」に引数を渡し、明示的に基底クラスのコンストラクタを呼び出す必要がある。
詳しくはここ
例:public Enemy(Game game):base (game)

  • ガベージコレクション
メモリ管理と同義らしい。GCと略されることもある。
C#では自動的にやってくれる。メモリの確保と開放をある程度オートマチックにやってくれる。
車のマニュアルとミッションで言えばC#はマニュアル車っぽい。

クラスを基にした実際の値としてのデータのこと。クラスを「型」、インスタンスを「実体」として説明されることもある。
「オブジェクト」とほぼ同義語のように用いられることが多いが、実際にメモリ上に配置されたデータの集合という意味合いが強い。
例えば「名前、身長、体重」というクラスがあるとすれば、そのインスタンスは「田中、175、65」というように用いられる。
一つのクラスから複数のインスタンスを作ることができ、それぞれのインスタンスは違った値を持ちうる。
なお、ひな形となったクラスを表す際には「○○クラスに属するインスタンス」「○○クラスのインスタンス」という表現が用いられる。
最終更新:2012年04月05日 21:16