Software_CS3

☆CSharp その3
(VisualC#)

┌──┐
│目次│
├──┘
│◎文法(続々)
◆クラス定義 class
◆構造体 struct
◆プリプロセッサディレクティブ directive


◆クラス定義

修飾子 class クラス名
{
    メソッド、フィールド、プロパティなど宣言する
    コードブロック(クラスのメンバ)
}

※クラスは型となり、その型を元にインスタンスが生成される。インスタンスはオブジェクトと呼ばれる。

※クラスのアクセス修飾子は publicかinternal
⇒デフォルトはinternal

_◇クラスのメンバ
│ ①メソッド
│ ②フィールド
│ ③プロパティ
※規定のアクセスレベルは private

_◇フィールド
│ クラスで宣言した変数。
│ 修飾子 型 フィールド名;
※読み取り専用フィールド
│ 修飾子 readonly 型 フィールド名;

※フィールドは直接アクセスできてしまう
│ 外部クラスに公開する場合は、メソッド、プロパティ、インデクサを使う
│ 間接アクセスが推奨されている。

※修飾子を省略した場合のアクセスレベルはprivate

_◇プロパティ
│ 値を格納できる点はフィールドと同じ
│ 値を格納する前に値の検証可能
│ 変更したときにイベントを発行、メソッドを呼び出し可能

プロパティ宣言

修飾子1 型1 変数名1;

修飾子2 型2 プロパティ名;
{
    get
    {
        return 変数名1;
    }
    set
    {
        変数名1 = value;
    }
}

※修飾子
│ 通常は変数1は直接公開せず、プロパティを公開する
│ 修飾子1 private
│ 修飾子2 public
│ 型1と型2は共通とする。

※getアクセサ
│ プロパティの値を取得するためのコードブロック
※setアクセサ
│ プロパティの値を設定、更新するためのコードブロック
※valueキーワード
│ 型の暗黙のパラメータ
※get/setのどちらか一方を省略するこtで書き込み専用、読みだし専用のプロパティとできる。

※C# 3.0以降でのプロパティの自動実装

修飾子 型 変数名 { get; set; }

読み取り専用にするにはsetの前にprivateを置く

例)
│ private object[] Items { get; set; }

_◇イベント
│ クリックなどのアクション、メソッドの終了などを通知する手段。
│ デリゲートを使用して、その発生時に呼び出されるメソッドをカプセル化する。

修飾子 event デリゲート型 イベント名;

※イベントは呼び出し元から呼ばれるのではなく、受け口となる相手先のメソッドをコールバックする

_◇コンストラクタ
│ クラスのインスタンスを作成、初期化するためのメソッド。
│ コンストラクタのメソッドはクラス名と同じ。

※コンストラクタの宣言

修飾子 クラス名(パラメータリスト)
{
    コードブロック1
}

_◇デストラクタ
│ クラスのインスタンスをメモリから削除するときにランタイム実行エンジンにより呼び出し
│ リソースの解放などに使う。
※オブジェクトがどこからも参照されていない場合は、ガベージコレクションの回収の対象となる。

※オブジェクトを参照している変数にnull値を代入するか、変数が宣言されたスコープの外に出た場合に、その変数はオブジェクトを参照していない状態(null参照)となる。

※デストラクタをクラスに実装すると、ガベージコレクションによる回収の際に実行される。

※デストラクタ宣言

~クラス名()
{
    。。。
}

_◇インデクサ
│ クラスのインスタンスを配列にし
│ ⇒インデックスを付けアクセス。
│ getアクセサとsetアクセサにより構成
│ thisキーワードを使って宣言
│ 通常,修飾子1はprivate
│ 修飾子2をpublicにすることでアクセスを制御する。
│ 型1と型2は同じ型
│ 要素数1は整数リテラル値
│ 型3は整数型
│ valueキーワードはインデックサの暗黙のパラメータ

※宣言

修飾子1 型1[] 変数名1 = new 型1[要素数1];

修飾子2 型2 this[型3 変数名3];
{
    get
    {
        return 変数名1[変数名3];
    }
    set
    {
        変数名1[変数名3] = value;
    }
}

_◇ジェネリック
│ C#2.0以降
│ class定義の中では型をパラメータ化して扱う
│ インスタンス生成時に型を決定
│ かつコンパイル時の型チェックも行える
│ ※ジェネリックが効果的な局面=コレクション型のように不特定のデータ型を含む場合

※object型を使った実装でも、種々の型を扱えるメソッドを記述できる
│ ⇒object型には何でも入れることができる
│ ⇒意図しない型の値を入れるようなコードを書いてもコンパイル時には通ってしまう。

※フィールドにジェネリックを使うばあいの型シンボル名の指定

class クラス名<型シンボル>
{
    修飾子 型シンボル名 フィールド名;
}

※ジェネリックを使って宣言したクラスのインスタンスの作成
│ クラス名<型> 変数名 = new クラス名<型>(パラメータリスト);

例)

public class FixedSizeCollection<T>
{
    。。。
    以降 型シンボル T を使って要素の宣言
        private T[] Items;
        public T GetItem( 。。。 )
    などという形で記述

※ジェネリック型のTypeの取得
│ ①型パラメータに対して typeof 演算子を使う
│ ②型パラメータを使ってインスタンスを生成し、GetType()メソッドを呼ぶ

例)
│ Type t = typeof(SimpleGeneric<int>);

例)
│ SimpleGeneric<int> sgI = new SimpleGeneric<int>();
│  。。。
│ Type alsoGT = sgI.GetType();

※ジェネリックメソッド

修飾子 型 メソッド名<型シンボル名>(パラメータ)
{
    コードブロック
}

_◇デリゲート
│ メソッドを参照する型。
│ ⇒デリゲートにメソッドを代入することで、デリゲートはそのメソッドと同様に動作

修飾子 delegate 型 デリゲート名(パラメータリスト);

※デリゲートの型はデリゲート名で定義される。

※デリゲートが呼び出されると、デリゲートに関連づけられたメソッドが呼び出される

※デリゲートは、コード中でよびだされるメソッドのシグネチャと返り値についての情報を保持する

※デリゲートオブジェクトをメソッドの引数に指定することができる
│ ⇒構造体やクラスメンバとしてデリゲートオブジェクトへの参照を保持できる

※実際にコードが実行される時点で、呼び出されるメソッドについての情報が得られるようになる
│ ⇒コード作成時点では把握できない

※デリゲートの良い応用例=Windowsフォームのコントロール
│ コントロールの発生時点では、各イベントが発生した場合に実行すべきメソッドを把握できない
│ ⇒デリゲートを公開
│ ⇒コントロールを利用する側で各イベントのメソッドをイベントハンドラに関連付ける

例)
マウスボタンのクリック
ボタンのオブジェクト
Click(this, new EventArgs());
⇒パラメータ値がイベントハンドラに渡される
protected void Button1_Click(object sender, EventArgs e)
{
。。。

※場合によっては、メソッドに関連づけられたthisオブジェクトを表すこともある

※デリゲートを呼び出す場合には、デリゲートを参照する変数名(デリゲート変数名)をメソッド名のように使う

例)
delegate void MyDelegate(string name);

。。。
クラス定義の中で
│ 実際に処理をおこなうメソッド SayHelloを記述

ラップするメソッドを指定してデリゲートをインスタンス化する
MyDelegate handler = SayHello;

インスタンス化したデリゲートを呼び出す
handler(“Hello”);
または
handler.Invoke(“Hello”);

※マルチキャストデリゲート
│ 1度のメソッド呼び出しで、複数のメソッドを呼び出す。
│ 通常、シーケンシャルに呼び出される。
│ ⇒パラレル呼び出し:GetInvocationListメソッドによりDelegateオブジェクトの配列を取得して処理

※デリゲートへのメソッドの追加、削除

演算子 +, – を使う
例)
handler += method;

Delegate.Combineメソッド
Delegate.Removeメソッド
Delegate.RemoveAllメソッド
を使う

※メソッドの非同期実行

_◇アクセス修飾子
│ アクセスのスコープを定義する。

①public
│ どこからでもアクセスできる
②protected
│ 派生クラスからのみアクセスできる
③private
│ 宣言したクラスの本体内でのみアクセスできる
④internal
│ 同じアセンブリ内でのみアクセスできる
⑤protected internal
│ 現在のアセンブリまたは格納クラスから派生した型からのみアクセスできる

_◇インスタンスの作成

型 変数名 = new コンストラクタ;

※オブジェクト初期化子(C# 3.0)
│ メンバの値を初期化できる。

型 変数名 = new コンストラクタ名 {メンバ1=値1, 。。。};

※コレクション初期化子
│ コレクションクラスのオブジェクトを作成する際にコレクションの値を初期化できる

型 変数名 = new コンストラクタ名 {値1, 。。。};

_◇クラスの現在のインスタンスの参照
│ thisキーワードを使うことで、クラスの現在のインスタンスを参照
│ thisをつければ、クラスのメンバ、つけなければメソッドのローカル変数といった区別が可能。

_◇インスタンスメンバと静的メンバ

※インスタンスメンバ
│ インスタンス作成後にアクセスできる

※静的メンバ
│ インスタンスに依存しない。
│ static修飾子を使う。

※メンバが全て静的メンバであれば、クラスを静的クラスとして宣言できる。

※静的メンバを参照する場合には、クラス名を使って参照する。

※拡張メソッド(C# 3.0)
│ 静的メソッドとしてだけでなく、インスタンスから拡張メソッドとして呼び出すことが可能。
│ 静的メソッドの第一パラメータのに修飾子thisを指定する。

_◇オーバーロード
│ overload
│ 同じ名前であってもシグネチャが違うメソッドを宣言できる。

※コンストラクタもオーバーロードできる。
│ ⇒「派生的」コンストラクタから「プライマリ」コンストラクタを呼び出す場合 :this(。。。) を使う

例)
public Class( 。。。 ) : this( 。。。)
{
。。。

_◇オーバーライド
│ 派生クラスで、シグネチャを変えずに継承した機能を拡張または変更する。

※非仮想メソッドまたは静的メソッドはオーバーライドできない。

①基本クラスでvirtualキーワードを使って仮想メンバとして宣言することによて派生クラスでそのメンバをオーバライドできる。派生クラスではoverrideキーワードを使う。
②基本クラスでabstractキーワードを使って抽象メンバとして宣言することによて派生クラスでそのメンバをオーバライドできる。派生クラスではoverrideキーワードを使う。

※baseキーワードを使うことで、派生クラスから基本クラスのメンバにアクセスできる。

※それ以上のオーバーライドの禁止
│ sealedキーワード
│ ⇒オーバライドしたメンバのある派生クラスをさらに継承したクラスでさらなるオーバライドは不可

_◇インターフェイス
│ クラスで実装する必要のあるメンバのシグネチャを定義
│ ⇒インターフェイスを実装するクラスでは、インターフェイスで定義されたあらゆるメンバの実装を厳密に行う必要がある。

※インターフェイス
│ メソッド、プロパティ、イベント、インデクサを組み合わせて構成できる
│ フィールドを含めることはできない

interface インターフェイス名
{
    。。。 メンバのシグネチャを定義するコード 。。。
}

※インテリセンスにより、実装のためのコードをクラスに自動追加することができる。

※インタフェースのコードブロック内でアクセス修飾子を省略するとinternalとなる。
│ (クラスや構造体の内部だとprivateがデフォルト)

※インタフェースを実装したクラスを呼び出す場合、インタフェース経由で使う

例)定義例

interface インターフェイス名
{
    シグネチャを記するコードブロック
}

例) プロパティのシグネチャ

int x
{
    get;
    set;
}

例)メソッドのシグネチャ
void SetCoordinate(int x);

※インターフェイスを実装するクラス定義

class MyClass : iMyInterface
{
    。。。
}

※複数のインターフェイスを実装する場合

class MyClass : iMyInterface1, iMyInterface2
{
    。。。
}

※インタフェースを介した呼び出し
MyClass obj = new MyClass();
。。。
iMyInterface1 im1 = (iMyInterface1)obj;
。。。
im1.インタフェースで定義されたメソッド、プロパティ

_◇部分クラス、部分メソッド
│ partialキーワード
│ クラスを宣言するコードを部分クラスとして複数のファイルに分割できる。

※C# 3.0

※部分メソッド
│ partial キーワードにより、メソッドを宣言するコードを定義宣言と実装宣言に分割
│ 部分メソッドのスコープは暗黙的にはprivateでかつ、void
│ ⇒部分メソッドは部分クラス内で引数と返り値を実装なしで宣言、別な場所で実装を記述
│ ⇒コンパイラは実装が見つけられないと自動的に定義を削除する

※部分型(クラス)定義
│ クラス、構造体、またはインターフェイスの定義を複数のファイルに分割できる
│ ⇒全ての部分クラスの定義が見つかるまでコンパイラは完全なコンパイルを保留
│ ⇒部分クラスは純粋コンパイラの機能であり、コンパイルされた中間言語には影響しない

例)IDEが定義するテンプレート
│ UIロジック、デザイナが自動生成するコードなどが分離したクラスとして定義されている

※実装例
│ インタフェースの実装コードをクラスのメインのコードから分離する。

_◇usingステートメントとスコープの定義

①usingステートメントによりスコープを定義できる。
②スコープの外部ではオブジェクトが廃棄される。
③IDisposableインタフェースを実装する必要がある。

using (変数名 = new クラス名(パラメータリスト))
{
    。。。
}

_◇クラスの継承
│ クラスが継承されると、
│ ⇒継承先のクラスは継承元の非プライベートなメソッド、フィールド、プロパティ、イベントを継承する。

修飾子 class クラス名 : 基本クラス名
{
    。。。
}

※基本クラス Base Class
※派生クラス Derived Class

※インテリセンスにより、基本クラスから継承されたメンバが表示される。

※Windowsフォームもクラスなのでクラスメンバとともに継承できる。

例)
継承元を示すコードを以下のように明示すれば継承できる。
継承されたコントロールには左上に継承されたコントロールであることが示される。

public partial class Form2 : Form1

※クラスの継承の禁止
sealedキーワードにより、シールクラスとして宣言することで継承を禁止できる。

例)
sealed class MySealedClass

※継承元クラスのコンストラクタの呼び出し
継承先クラスのコンストラクタから : base(。。。) により呼び出す。

例)

class ClassDerived : ClassBase
{
 。。。
    public ClassDerived(。。。) : base (。。。)
    {
        。。。

_◇継承とインタフェース
│ クラスの継承もインタフェースの実装もクラス宣言のクラス名につづいて「:」を書いて記述する。
│ 違いは以下のとおり。
│  インターフェイス
│  何個でも記述できる
│  継承
│  1個だけ

※C++と異なりC#では、多重継承は禁止
│ ⇒このため、インタフェースがある
│ ⇒機能性を継承するときは継承
│ ⇒呼び出し方法を合わせるときはインターフェイス


◆構造体

修飾子 struct 構造体名
{
    メソッド、フィールド、プロパティなど宣言する
    コードブロック(構造体のメンバ)
}

※構造体は、クラスに類似しているが、値型であることが異なる。
│ それに伴う制限がある。
│ ⇒処理によってはクラスより高速に扱えるが取り扱い上の危険性がある

│ クラスの場合、
│  クラスの型 変数
│  として生成される変数は、参照型の変数
│  ⇒それにnewで生成されるクラスの実体を指すポインタを代入することで操作可能となる
│ 構造体の場合、
│  構造体の型 変数
│  として生成された変数は、構造体の全メンバを含む値型の変数

①よってnew演算子を使わなくてもインスタンス化はできる。
│ ※その場合は、全フィールドに値を割り当てる必要がある。
│ ※new演算子を使ってコンストラクタを呼び出してのインスタンス化も勿論できる。
②インスタンスフィールドの初期化子による初期化はできない。ただし、静的フィールドは初期化できる。
③クラスではデフォルトコンストラクタ(引数をとらない)を定義できたが、構造体でコンストラクタを定義する場合は、必ず引数が必要になる。
│ ※明示的にコンストラクタを定義しない場合は、
│  new 構造体名()
│ で初期化できる。
④デストラクタは宣言できない
⑤構造体をメソッドに渡したり、代入する場合は、値型なので実体メモリがコピーされて渡されることになる。※ref,outにより参照渡しとすることができる
⑥インタフェースを実装できる
⑦構造体の継承はできない。


◆プリプロセッサディレクティブ

_◇#define, #undef

#define シンボル
│ シンボルをtureにする
#undef シンボル
│ シンボルをfaluseにする

※C#の#defineではシンボルに値を割り当てることはできない。コンパイラオプションの定義用。マクロや定数の作成も不可(エラーを招きやすいため)

マクロ⇒ジェネリック
定数⇒enum変数

で代用する。

_◇#if。。。#elif。。。#else。。。#endif

#if シンボルまたは条件式
 。。。
#elif シンボルまたは条件式
 。。。
#else
 。。。
#endif

_◇#line
#line 行番号 “ファイル名”
│ エラーや警告で出力される行番号とファイル名を変更する

#line default
│ 行番号や”ファイル名”指定を元に戻す

#line hidden
│ #line defaultまで、後続の行をデバッガから隠す

_◇#error
#error エラーメッセージ

_◇#warning
#warning 警告メッセージ

_◇#region, #endregion
│ コードエディタのアウトライン機能で展開折りたたみのできるコードブロックを指定

例)
#region Code Block1
。。。
#endregion