MainMenu

MainMenuは、ウィンドウ上部のメインメニューのクラス・・・。

MainMenu クラス (System.Windows.Forms)

ただし、これは.NET Framework 1.1までの古いクラス・・・。
2.0以降はMenuStripを使うのが推奨・・・。

f:id:BG1:20170310111919p:plain

[ツール]-[ツールボックスアイテムの選択]から、

f:id:BG1:20170310111958p:plain

フィルタで"MainMenu"を絞り込んで、最終的にグローバルのMainMenuにチェックを入れる・・・。

f:id:BG1:20170310112055p:plain

ツールボックスにMainMenuが出てきたら、

f:id:BG1:20170310112139p:plain

上の方に設置するとこうなる・・・。

f:id:BG1:20170310112314p:plain

デザイナでメニューアイテムを追加し、編集・・・。

f:id:BG1:20170310112435p:plain

プロパティのイベントで、Clickのところをダブルクリックで、ハンドラが生成されるので、

menuItem3_Click("開く"は3番目に追加したからかな・・・。)にメッセージボックスで"Open!"と表示するように・・・。

ちなみにハンドラの登録は、Form1.Designer.csの、

ここに・・・。(なんで、ファイルが分かれているのにできるかは後述・・・。)

f:id:BG1:20170310113245p:plain

実行すると、デザインした通りにメニューが設置されてる・・・。

f:id:BG1:20170310113325p:plain

"ファイル"から"開く"を選択すると、

f:id:BG1:20170310113348p:plain

"Open!"と表示される・・・。

Sample/dotnet/MainMenu/MainMenu/src/MainMenu_ at master · bg1bgst333/Sample · GitHub

EventHandler

EventHandlerは、ボタンなどのコントロールで発生したイベントに対する処理を書くイベントハンドラメソッド用のデリゲート・・・。

EventHandler デリゲート (System)

これまで、自動で生成されていたイベントハンドラとその登録処理を自前で手書きで書いてみる・・・。

f:id:BG1:20170309224816p:plain

Windowsアプリケーションで、

f:id:BG1:20170309224849p:plain

Form1にButtonを貼り付ける・・・。

f:id:BG1:20170309224944p:plain

ここで、これまでならbutton1でダブルクリックで、ハンドラを自動生成していたが、今回はあえてしない・・・。

Form1.csを開いて、

イベントハンドラをhandlerという名前で定義・・・。
(あえてオリジナルとは違う名前にする・・・。)
引数はobject型とEventArgs型で名前は適当に・・・。
戻り値はvoid・・・。
handlerが呼ばれたら、"Event!"とメッセージボックスで表示・・・。

Form1のコンストラクタでは、InitializeComponentの後にhandlerを呼び出すEventHandlerデリゲートをbutton1.Clickに登録・・・。
button1が押されたら、button1.Clickが参照され、ハンドラが呼ばれるという仕組み・・・。

f:id:BG1:20170309225904p:plain

button1を押すと、

f:id:BG1:20170309225915p:plain

"Event!"が表示された・・・。

Sample/dotnet/EventHandler/EventHandler/src/EventHandler_ at master · bg1bgst333/Sample · GitHub

ジェネリクス

ジェネリクスC++でいうテンプレートのようなもので、型をパラメータで受け取れるようにすることで、さまざまな型で共通の処理を使うことができる・・・。

C++でやったスワップクラスをC#で作る・・・。

Swap.csは、

クラス名の後にを付けるだけで<T>が汎用型であることが示せる・・・。
交換する値x, yは、それぞれX, Yというプロパティで設定と取得を定義・・・。
メソッドDoSwapでxとy(XとY)を交換する・・・。

MainClass.csは、

最初は、int型を受け取るiSwapの10と20の交換・・・。
次は、string型を受け取るstrSwapの"ABC"と"XYZ"の交換・・・。

X = 10, Y = 20
X = 20, Y = 10

X = ABC, Y = XYZ
X = XYZ, Y = ABC
続行するには何かキーを押してください . . .

交換できてる・・・。

Sample/cs/Generics/Generics/src/Generics at master · bg1bgst333/Sample · GitHub

属性

属性は、自作のメソッドやクラスに、既定または独自の機能や情報を付加する仕組み・・・。

今回は、自作のメソッドにConditionalAttributeを付ける・・・。

ConditionalAttribute クラス (System.Diagnostics)

ConditionalAttributeは、前回のような条件付きコンパイルに使うシンボルが定義されていたらそのメソッドを呼び出すというもの・・・。

// 名前空間の登録
using System;               // 共通データ型と基本クラス(System名前空間)
using System.Diagnostics;   // システムプロセスやイベントログとの対話するためのクラス.(System.Diagnostics名前空間)

// メインクラス
class MainClass // MainClassクラスの定義
{

    // メインメソッド
    static void Main()  // Mainメソッドの定義
    {

        // 属性付きメソッドTestを呼ぶ.
        Test(); // Testを呼ぶ.

        // "ABCDE"と出力.
        Console.WriteLine("ABCDE"); // Console.WriteLineで"ABCDE"と出力.

    }

    // 属性付きメソッドTest
    [Conditional("TEST")]   // 属性Conditional("TEST")は, シンボル"TEST"が定義されていれば呼ばれる.
    static void Test()
    {

        // "Test"と出力.
        Console.WriteLine("Test");  // Console.WriteLineで"Test"と出力.

    }

}

ConditionalAttributeを使うには、System.Diagnosticsが必要・・・。
メソッド定義の上に、"["と"]"の間に"Conditional"(属性のクラス名から"Attribute"を除いたもの)と書く・・・。
さらにその次の括弧の中にパラメータとしてシンボル"TEST"を書く・・・。
これで、このメソッドはConditionalAttributeという属性を持つ・・・。
"TEST"が条件付きコンパイルのシンボルとして定義されていれば、このメソッドTestが呼ばれた時にちゃんと実行される・・・。
定義されていなければ実行されない・・・。

このまま実行すると、

ABCDE
続行するには何かキーを押してください . . .

メソッドTestが実行されない・・・。

先頭で#defineディレクティブで"TEST"を定義すると、

Test
ABCDE
続行するには何かキーを押してください . . .

メソッドTestが実行された・・・。

Sample/cs/Attribute/Attribute/src/Attribute_ at master · bg1bgst333/Sample · GitHub

#defineディレクティブ

#defineディレクティブは、シンボルを定義するときに使う・・・。
ファイルの先頭にしか定義できない・・・。(コメントとかぐらいは上にあっても大丈夫みたい・・・。usingとかよりは上・・・。)

最初に、

// 名前空間の登録
using System;       // 共通データ型と基本クラス(System名前空間)

// メインクラス
class MainClass // MainClassクラスの定義
{

    // メインメソッド
    static void Main()  // Mainメソッドの定義
    {

        // TESTが定義済みならコンパイル対象.
#if TEST

        // "Test"と出力.
        Console.WriteLine("Test");  // Console.WriteLineで"Test"と出力.

#endif

        // "ABCDE"と出力.
        Console.WriteLine("ABCDE"); // Console.WriteLineで"ABCDE"と出力.

    }

}

前回のコードと同じものをそのまま実行すると、

ABCDE
続行するには何かキーを押してください . . .

こうなるが、

このように、先頭で#defineディレクティブでシンボルTESTを定義しておくと、

Test
ABCDE
続行するには何かキーを押してください . . .

"Test"が出力される・・・。

Sample/cs/defineDirective/defineDirective/src/defineDirective at master · bg1bgst333/Sample · GitHub

#ifディレクティブ

C#にもプリプロセスがある・・・。
#ifディレクティブは、指定されたシンボルが定義されているときに、#endifまでのプログラムがコンパイル対象となる・・・。
C言語C++と違い、マクロの定義ができないので、マクロの値ではなく、シンボルが定義されているかどうかを評価する・・・。

TESTというシンボルが定義されていたら、Console.WriteLineで"Test"と出力する・・・。
そのまま、実行すると、

ABCDE
続行するには何かキーを押してください . . .

定義してないから、"Test"は出力されない・・・。

f:id:BG1:20170309124058p:plain

プロパティから、

f:id:BG1:20170309124131p:plain

[ビルド]の[条件付きコンパイルシンボル]にTESTを追加する・・・。

これで実行すると、

Test
ABCDE
続行するには何かキーを押してください . . .

シンボルが定義されているから、"Test"が出力された・・・。

Sample/cs/ifDirective/ifDirective/src/ifDirective at master · bg1bgst333/Sample · GitHub

#if文

#if文は、プリプロセッサディレクティブのひとつで、指定されたマクロの値が真(true)の時、#endifまでのプログラムが有効となりコンパイル対象となる・・・。
偽(false)の時は、コンパイル対象にならないので、実行もされない・・・。
つまり、コメントアウトと同じようなものだが、これを使うとマクロの値によって条件付きコンパイルができる・・・。

/* ヘッダファイルのインクルード */
#include <stdio.h> /* 標準入出力 */

/* マクロの定義 */
#define SWITCH 0

/* main関数の定義 */
int main(void){

/* SWITCHが真ならコンパイル対象になるので実行される. */
#if SWITCH

  /* "Switch On"と出力 */
  printf("Switch On\n"); /* printfで"Switch On"と出力. */

#endif

  /* "ABCDE"と出力 */
  printf("ABCDE\n"); /* printfで"ABCDE"と出力. */

  /* プログラムの終了 */
  return 0;

}

SWITCHマクロを0にしておく・・・。
"Switch On"を出力する部分はSWITCHが真(つまり0以外)の時、コンパイル対象になるので、

$ gcc if_directive.c -o if_directive
$ ./if_directive
ABCDE
$

実行されない・・・。
しかし、

このようにSWITCHマクロを1にすると、

$ gcc if_directive.c -o if_directive
$ ./if_directive
Switch On
ABCDE
$

となって、"Switch On"の出力が実行された・・・。

Sample/c/if_directive/if_directive/src/if_directive at master · bg1bgst333/Sample · GitHub