実は、標準ライブラリにデリゲート(delegate)が準備されています。
ようは「よく使うデリゲートの形は、わざわざ定義しなくても出来るよ」ってことです。
これを使って、前回の内容を標準ライブラリで置き換えた場合どうなるのかを紹介していきたいと思います。
準備されているDelegate
今回は、2つに絞って紹介します。
それは、【Action】と【Func】です。
ざっくりの違いは、『戻り値が有無』です。
戻り値がないDelegateには【Action】を使用します。
戻り値のあるDelegateには【Func】を使用します。
置き換えの方法
【Action】に置き換える
戻り値なしのデリゲートを使用する時は、下記のように定義しました。
private delegate void TestProcess(string str);
これは、[TestProcess]という名前で引数に文字列が必要な戻り値のないデリゲートです。
これを置き換えると下記のように置き換える事が出来ます。
private Action<string> TestProcess;
随分と短くなりましたね。スッキリした印象になります。
書き方的には「Action<引数1の型,引数2の型,….>」と書くようになります。
引数のないときは、「Action」のみになりますね。
【Func】に置き換える
戻り値ありのデリゲートを使用する時は、下記のように定義しました。
private delegate int TestProcess(string str);
これは、[TestProcess]という名前で引数に文字列が必要な戻り値のあるデリゲートです。
これを置き換えると下記のように置き換える事が出来ます。
private Func<string, int> TestProcess;
戻り値があるので<>の中の最後は、戻り値の方を入れる必要があります。
書き方的には「Func<引数1の型,引数2の型,….,戻り値の型>」と書くようになります。
引数のないときは、「Func<戻り値の型>」になりますね。
サンプルの作成
前回の記事で作ったプロジェクトを置き換えていきたいと思います。
【C#】デリゲート(delegate)の使い方 | 育児パパの人生備忘録 (t19488sns.com)
※リセットボタンの処理は匿名メソッドに修正済み(この内容は下記記事)
【C#】匿名メソッド(無名関数)の使い方 | 育児パパの人生備忘録 (t19488sns.com)
操作画面
簡単にコントロールの説明
textBox1 :入力文字 btnGetRow :行数を取得する。取得した内容はlabel1に表示する。 btnGetLength:文字数を取得する。取得した内容はlabel2に表示する。 btnBoth :行数&文字数を取得する。取得した内容はlabel1/label2に表示する。 btnReset :label1/label2の表示を空白にする。 label1 :行数表示用 label2 :文字数表示用
定義
前回定義していたデリゲートを使う必要がなくなりましたので、コメントアウトです。
//private delegate void TestProcess(string str);
次に引数にデリゲートをを使う関数です。
private void test(string dt, Action<string> proc)
{
proc(dt);
}
「TestProcess」という名前のデリゲートはなくなったので、Actionで置き換えました。
処理の紹介
今回、処理を変更するのは、2つです。
[行数の取得ボタン]と[両方(行数&文字数)取得ボタン]です。
行数取得ボタンの処理
行数の取得のボタン[btnGetRow]がクリックされた時の処理
private void btnGetRow_Click(object sender, EventArgs e)
{
//instanceを生成して実行するパタン
//TestProcess _getrow = new TestProcess(GetRows);
//_getrow(textBox1.Text);
//Actionによる書き換え
Action<string> proc = new Action<string>(GetRows);
proc(textBox1.Text);
}
前回は、定義に[TestProcess]という名前のDelegateを定義していましたが、その形式で使えるAction<>があるので、Action<string>のインスタンスを生成します。
両方[行数&文字数取得]ボタンの処理 ★マルチキャストデリゲートを使う
インスタンスを生成した場合、複数の関数を同時(順次)に実行できるようにできます。
これを「マルチキャストデリゲート」です。これは、Actionの時でも使えます。
private void btnBoth_Click(object sender, EventArgs e)
{
//行数取得の関数を生成する。
//TestProcess _proc = new TestProcess(GetRows);
//文字数取得の関数を追加する。
//_proc += GetLength;
//実行する。
//_proc(textBox1.Text);
//Actionによる書き換え
Action<string> _proc = new Action<string>(GetRows);
_proc += GetLength;
_proc(textBox1.Text);
}
関数を加算する事で、1つのデリゲート内で複数の関数を処理する事ができます。
処理の紹介(変更いらず)
文字数取得ボタンの処理
文字数の取得のボタン[btnGetLength]がクリックされた時の処理は変更がいりません。
なぜなら、関数の引数の名前が変わっただけで、内容は同じだからです。
private void btnGetLength_Click(object sender, EventArgs e)
{
//引数で引き渡して実行するパタン
test(textBox1.Text, GetLength);
}
実行結果
実行結果は前回と同じなのです。(アウトプットは変えずに、手段を変更しただけなので)
まとめ
前回、独自のdelegateを定義しましたが、標準ライブラリで準備されているので、置き換えてみました。
これは「アウトプットの為の手段」です。
「delegateを使った方がいい!」とか「Actionを使った方がいい!」とかの話ではありません。
ただ人が書いたソフトを見る機会が多い人は、覚えていた方がいいと思います。
一人でソフトを書く人は、書きやすい方でいいと思います。
また、匿名メソッドで書いた内容をActionに置き換える方法が分かりませんでした。
別の置き換える方法として、ラムダ式で置き換える方法を次回紹介したいと思います。
業務でプログラミング(C#/VB/Python)を作っている。
挫折を何回も繰り返し、幾度の壁を乗り越えてきた。
乗り越えてきた事を忘れないように記録に残す。
同じ思いをしている人への情報提供になれたらと思う。
基本は初心者に向けたプログラムの情報を提供する。
コメント