はじめに ※読み飛ばし可
人生初のQita投稿ということもあり、この記事を書いているやつがどんな人間かを簡単に自己紹介させてください。
見出しにも書いてあるとおり、内容にはまったく関係ないので読み飛ばしていただいても構いません。
わたしは新卒で6年間働いたSIer企業を辞めて、この2022年の5月から自社開発企業に転職しました。
前職は大規模で社会インパクトも大きいながらも、技術スタックおよび開発プロセスともに非常にレガシーなシステムの開発に携わっておりました。
規模に比例した責任感とやりがい、会社自体の安定感に魅力はあったものの、立ち位置上「コードが書けないマネージャ」まっしぐらなキャリアに違和感と危機感を持ち、とうとう思い切って転職を決意しました。1
転職先では、これまた人生初のC#での開発現場でエンジニアとして新しいキャリアを歩んでいます。正直、わからないことだらけで文字通り毎日が勉強ですが、自分の整理も兼ねて少しずつアウトプットしていこうと思い、Qiitaをはじめました。
ネット上には詳しい方がいくらでもいるので、そういう方からすると説明不足や分かりづらい点があるかと思いますが、もし誤りなどがあればご指摘いただければと思います。
この記事でわかること
この記事のテーマはC#の「デリゲート」です。C#を勉強してて、2番目にピンとこなかった概念です2。「デリゲートってこういうものか」ってのがわかってもらうのがこの記事のゴールです。
この記事で扱わないこと
匿名メソッドやLINQについては、扱いません。また、C#としてあらかじめ定義されているデリゲートのクラス「Action」、「Func」も一旦置いておきます。
結局、デリゲートってなんなのか?
前置きが長くなりました。
デリゲートを一言で言えば、メソッドを参照できる型。この型で作った変数にはメソッドを格納できる。3
宣言の仕方
デリゲートは、自分で宣言できる型。宣言のために「deligate」キーワードを使う。
public delgate bool hoge(int value);
で、デリゲートの結局なにがうれしいのか
正直わたしはこの説明を受けて「変数にメソッドが格納できるから何?」状態だったので具体例で考えてみます。実際は、ラムダ式を使うので、以下の例のような書き方はしないのですが、わかりやすさのためにラムダ式が導入される前の想定で書いています。
(例)
public delegate bool JudgementCondition(int value); //デリゲートの宣言
public int Do() {
var numbers = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,};
JudgementCondition judgementCondition = IsEven // デリゲート型「JudgemntConditon」にIsEvenメソッドを代入
var count = Count(number, judgementCondition);
Console.WriteLine(count); // 5
}
// nが偶数か調べる
public bool IsEven(int n); {
retun n % 2 == 0;
}
// 判定条件に当てはまる要素をカウントする
public int Count(int[] number, JudgementCondition judgementCondition){
int count = 0;
foreach (var n in numbers) {
if (judgementCodition(n) == true)
count++;
}
}
今回作ったデリゲートは「int型の引数を受け取って、bool型の戻り値を返す」型です。したがって「int型の引数nが偶数かどうかbooleanで判定するメソッド」IsEvenを代入することができます。
でも、代入できるはIsEvenだけではありません。同じように奇数かどうか調べるメソッドとか、5の倍数かを調べるメソッドも同じように代入することができるわけです。
つまり、デリゲートに代入するメソッドを変更することで、さまざまな条件で要素数をカウントできるようになりました。
逆に、デリゲートを使わないと、判定条件ごとにいくつものCountメソッドを作らないといけません。
実際は、これを「匿名メソッド」と「ラムダ式」を使うことでよりスッキリ書くことができます。デリゲートという概念があるから、日頃お世話になってるラムダ式が使えるということだと理解しています。
名前から考える「デリゲート」
わたしは何か新しい概念を学ぶときに、その概念の名前や語源を結構意識します。その名前の由来や語源がピンとこないとあまり頭に入ってきません。
「deligate」の単語の意味としては「代表者、代理人」があります。よく「委譲する、委任する」の動詞で解説されますが、わたしは「代表者、代理人」の訳のほうがしっくりきました。推測ですが、処理自体は参照先の実際のメソッド(例でいうと、isEven)が担っており、あくまでデリゲート自体は代表者である。というニュアンスだと思っています。
参考文献
- 『実戦で役立つ C#プログラミングのイディオム/定石&パターン』:実践的かつわかりやすくおせわになっている1冊。C#の基本文法を一通りやったあとにオススメ。