Help us understand the problem. What is going on with this article?

イベント part1 (十週目の学習)

More than 1 year has passed since last update.

モチベーションも大事だと思うので覚書として使用します。

十週目の感想
今週は例外処理で少しずれ込みました、学習は仕様の確認だけにして、来週Versionアップしたつもりで頑張ろうと思います。。脳が休息を欲してる(気がした)のでこの期間にリフレッシュして緩めました♨

ちょうど十週間突破したので、何週間表示はやめようと思います。あと既存という字はきそんと本来いうらしいです。てことは現存げんそんか…


イベント

イベントは、GUI(グラフィカルユーザインタフェース)におけるユーザ入力やクリックの事。
何が起こったら(イベント)どうする(イベントハンドラ)。

使用には、
①デリゲート
Delegateか中にAction(どちらもDelegate(メソッド参照))作る。
②イベントフィールド
最初のクラスをイベントフィールドとする
(event宣言(先程のデリゲートを宣言のターゲットにする(イベントハンドラがあるメソッド呼び出し可能にするため)
と条件(if(EventName !=null)EventName(引数);)も作成)
③イベントハンドラ
2.3個目のクラスに呼び出すメソッド作成(イベントハンドラ内容)
③Main
イベ名 += new デリ名(実行メソッド)
event発生時実行文EventName();
※呼出は抽象的ならオーバーライド(上書き)(引数同じ)メソッド使ってもいい

例外処理としてデリゲートで各メソッド呼び出して発生(本来トリガーif)
例外処理としてデリゲートで各メソッド呼び出して発生(本来トリガーif)
class MyEvent
{
    //public Action MyDelegate;
    public event MyDelegate EventName;

    public void OnEventName()
    {
        if (EventName != null)// null例外
            EventName();//イベント発生
    }
}

class MyClass
{
    public void Show()
    {
        Console.Write(1);
    }
}

class MyClass2
{
    public void Show2()
    {
        Console.Write(2);
    }
}

class Event1
{
    public static void Main()
    {
        MyClass mc = new MyClass();
        MyClass2 mc2 = new MyClass2();
        MyEvent me = new MyEvent();

        // イベントハンドラ
        me.EventName += new MyDelegate(mc.Show);
        me.EventName += new MyDelegate(mc2.Show2);
    //me.EventName += () => mc2.Show2; λでスリム

        me.OnEventName();//イベント発生
    }
}

クラスに分割してデリゲートでイベント(一桁加算機)
neko.kasanki.delegate
// 何かデリゲートの学習してるみたいだけど、元来のイベント処理手順がわかった。
using System;

// 1.delegate
delegate void Handler(char ch);
// 2.field
class EventClass
{
    public event Handler KeyHit;

    public void OnKeyHit(char ch)
    {
        if (KeyHit != null)
            KeyHit(ch);
    }
}
// 3.handler
class Show
{
    int sum = 0;

    public void KeyShow(char ch)
    {
        if (Char.IsDigit(ch))
        {
            int a = (int)char.GetNumericValue(ch);
            sum += a;
            Console.Write($"+{a}\n");
            Console.Write($"={sum}\n");
        }
        else if (ch == 'c')
        {
            sum = 0;
            Console.Write("合計がクリアされました\n");
        }
        else return;
    }
}
// 4.Main
class Event2
{
    public static void Main()
    {
        ConsoleKeyInfo cki;

        EventClass ec = new EventClass();
        Show s = new Show();

        ec.KeyHit += new Handler(s.KeyShow);

        while (true)
        {
            if (Console.KeyAvailable)
            {
                cki = Console.ReadKey(true);
                if (cki.KeyChar == 'x')
                    break;
                else ec.OnKeyHit(cki.KeyChar);
            }
        }
    }
}

(来週)クラスに分割してオーバーライドメソッドでイベント(一桁加算機)
neko.kasanki.override
// 何かデリゲートの学習してるみたいだけど、元来のイベント処理手順がわかった。

このようにイベントハンドラはユーザイベントを想定し、条件をトリガーとして、イベント時呼び出されます。


コールバック

処理呼出(コールバックだから呼戻し?)今までの学習内で5つ程ありました。

Ⅰ.普通にメソッド引数を渡す
処理メソッドに引数定義、①返す用のint w②代入w=x+y③返す用return w設定。
Main関数で①返される用のint result②渡す用のresult=渡したい関数名(引数の値)③それを用いた処理文

Ⅱ.コンストラクタ
(クラス名と同じにする、Mainにて呼出時インスタンス化、Test test = new Test();)

Ⅲ.オーバーライド
(元メソッドをpublic virtual~として、派生クラス先はpublic override~このようにオーバーライドメソッド作る)
(意味は上書き)(条件は引数同じ)
memo.処理内容{return}にしとけば派生先で元メソッドでも{return}でそのクラス処理文に対してreturnで返される。

Ⅳ.デリゲート
①まずクラス外で宣言して 例delegate void DeleName(int a, int b)
②MainでデリゲートをNewインスタンス化か代入 例new DeleName(c.Minus)
③最後に引数代入と共に呼び出し 例d1(2, 1)

Ⅴ.抽象メソッド
(規格みたいな感じ、派生クラス作ってパーツ作れる)①abstract class~、public abstract int~、という風に2回つけて設定
②実装クラスのメソッドにはoverrideつける※基本クラス下の場合
interface…メソッドではなくクラスと同列階層だが、抽象メンバを呼び出す。当然派生クラス先でパーツ化する。
abstractの利用価値下がる(interfaceだと自由に継承や複数設定ができ汎用性あるclass名: interface1, interface2, ...)

Ⅵ. ローカル関数 ←New!C#7
メソッドの中に書くメソッド

static void SampleMethod01()
{
// 親メソッドしかアクセス出来ないので修飾子いらない
int LocalFunc01(int a, int b)
=> a + b;

// ここより前で定義されているローカル関数の呼び出し
WriteLine($"LocalFunc01(1,2)={LocalFunc01(1,2)}");
// 出力:LocalFunc01(1,2)=3

※イベントアクセサやプロパティgetter、setterの本体で使える

Before:
public string FullName
{
    get
    {
        return FirstName + " " + LastName;
    }
}

// After:
public string FullName => FirstName + " " + LastName;
static void SampleMethod03()
{
  // ラムダ式でデリゲートを定義して使う従来の書き方
  Func<int, bool> IsOdd = (n) =>
    {
      return n % 2 != 0;
    };
  var odds = Enumerable.Range(1, 10).Where(IsOdd);
  WriteLine($"odds={string.Join(",", odds)}");
  // 出力:odds=1,3,5,7,9

  // ローカル関数も、通常のメソッドと同様にデリゲートとして扱える
  bool IsEven(int n)
  {
    return n % 2 == 0;
  }
  var even = Enumerable.Range(1, 10).Where(IsEven);
  WriteLine($"evens={string.Join(",", evens)}");
  // 出力:evens=2,4,6,8,10
}

ちなみにイベント呼出にはデリゲートとオーバーライドをよく見かけるのですが、
理由があるみたいなので試すのは端折りました。


次回は、オーバーライドで試してイベントプロパティやAction、Funcも確認したいと思います。
memo:発生頻度の低いイベントを数多く定義する場合は、イベントプロパティ

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away