C#のdelegateでできることは?便利な使い方やラムダ式についても紹介

C#のdelegateとは?
C#にはdelegateという文法があります。delegateとは日本語で「委譲」と訳され、任せるという意味になります。その通りに、C#のdelegateはメソッドを代入してその処理を「おまかせ」することができるのです。
delegateはC言語の関数ポインタという機能によく似ているのですが、この記事を読む人はC言語を知らない人も多いでしょう。そんな方々にもわかるように説明するので、是非この記事を読んでdelegateについて知って下さい。
C#のdelegateの基本的なサンプルプログラム
以下がC#のdelegateのシンプルなサンプルプログラムです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// デリゲート
delegate void DelegateMethod(int val);
static void Main(string[] args)
{
// ShowNumメソッドを委譲するデリゲート宣言
DelegateMethod dm = new DelegateMethod(ShowNum);
// デリゲートを経由してShowMesが呼ばれる
dm(100);
}
static void ShowNum(int num)
{
Console.Write("渡された値は {0} です。\n", num);
}
|
実行結果は、以下が表示されます。
1
|
渡された値は 100 です。
|
C#のdelegateで可能なこと4選
C#でdelegate型の変数にstaticな静的メソッドやクラスのインスタンスの動的メソッドを代入できます。またメソッドの追加や削除を動的に行うことができます。
1:メソッドの処理ができる
上の例について説明すると、delegateのDelegateMethodにShowNumという普通のメソッドを代入して、DelegateMethodの実体のdmを呼ぶことでShowNumが呼び出されるという流れです。
newで宣言しているのに「代入」と言いましたが、実際にnewしている箇所を以下のように記述することも可能です
1
2
3
|
DelegateMethod dm = ShowNum;
|
2:インスタンスメソッドを代入できる
C#のdelegateにはstaticな静的メソッドだけでなく、クラスのインスタンスの動的メソッドも代入できます。以下のように行います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Human
{
public void ShowMes() { Console.WriteLine("人間です。"); }
}
static void Main(string[] args)
{
Human hu = new Human();
DelegateMethod dm = hu.ShowMes;
dm();
}
|
HumanクラスのインスタンスhuのメソッドShowMesを、delegateのdmに代入しています。これを実行すれば以下のように表示されます。
1
|
人間です。
|
3:複数のメソッドを代入できる
C#のdelegateには複数のメソッドを追加できます。上のMainメソッドを以下のように変更し、ShowSpringというメソッドを追加しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static void Main(string[] args)
{
Human hu = new Human();
DelegateMethod dm = hu.ShowMes;
dm += ShowSpring; // ShowSpringを追加
dm();
}
static void ShowSpring()
{
Console.WriteLine("春が来ました。");
}
|
これを実行すると以下のように表示されます。
1
2
|
人間です。
春が来ました。
|
4:追加したメソッドを除去できる
delegateに+=でメソッドを追加すると、連続で実行されます。ただし引数と戻り値が同じタイプのメソッドしか追加できません。この例では追加するメソッドに引数がある場合や、戻り値がvoidではないメソッドを追加しようとしてもエラーになります。
またdelegateには+=による追加だけでなく-=による除去もできます。Mainメソッドを以下のように変えてみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
|
static void Main(string[] args)
{
Human hu = new Human();
DelegateMethod dm = hu.ShowMes;
dm += ShowSpring; // 追加
dm();
dm -= hu.ShowMes; // 除去
dm();
}
|
結果は以下のようになります。
1
2
3
|
人間です。
春が来ました。
春が来ました。
|
-=により2つあったメソッドが1つになったということです。
C#のdelegateの便利な使い方4つ
C#でdelegateを使用して条件判断処理を差し替える例を提示して、匿名関数を使用するように修正したり定義済みdelegateを利用するように修正してみます。またdelegateを使用したコールバック関数の例も提示します。
1:条件判断処理を差し替える
C#のdelegateは以下のようなケースで役に立ちます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
delegate bool JudgeMethod(int num);
static void Main(string[] args)
{
int[] ary = new int[] { 9, 3, 5, 2, 7, 8, 1, 6, 4 };
//aryの5より大きい値を表示する
JudgeMethod jm = JudgeOver5;
for (int i = 0; i < ary.Length; i++)
{
if (jm(ary[i])) { Console.Write(ary[i] + " "); }
}
Console.WriteLine("");
//aryの5より小さい値を表示する
jm = JudgeUnder5;
for (int i = 0; i < ary.Length; i++)
{
if (jm(ary[i])) { Console.Write(ary[i] + " "); }
}
}
static bool JudgeOver5(int val) { return val > 5; }
static bool JudgeUnder5(int val) { return val < 5; }
|
上のサンプルプログラムを実行すると、以下のように表示されます。
1
2
|
9 7 8 6
3 2 1 4
|
処理の流れは以下の通りです。
1.delegateのJudgeMethodにJudgeOver5を代入する。
2.JudgeOver5の判断で配列のaryの中から5より大きい値を取り出す。
3.JudgeMethodにJudgeUnder5を代入する。
4.JudgeUnder5の判断でaryの中から5より小さな値を取り出す。
このようにC#のdelegateは条件判断の処理を差し替えたい時に、便利に使えるのです。
2:匿名関数で代入するメソッドを省略する
上のサンプルのJudgeOver5やJudgeUnder5のような1行で済む短いメソッドはもっとコンパクトにすることができます。それが匿名関数です。上のサンプルのjmにJudgeOver5とJudgeUnder5を代入している箇所は、以下のように記述できます。
1
2
3
4
|
JudgeMethod jm = delegate (int val) { return val > 5; };
jm = delegate (int val) { return val < 5; };
|
これでJudgeOver5とJudgeUnder5は不要になります。
3:コールバック関数を代入する
コールバック関数とは非同期処理が終了した時に通知を行う関数のことです。
ここではdelegateを使用して、DoCallBackをコールバック関数として使用するC#のサンプルコードを示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CsDelegateCallback
{
class Program
{
// delegate型の宣言
public delegate void Callback(bool res);
static void Main()
{
Callback doCallBack = DoCallBack;
// 非同期処理開始
Task task = Task.Run(() => DoAsyncProc(doCallBack));
// 同期処理
for (int i = 0; i < 4; i++)
{
Thread.Sleep(1000);
Console.WriteLine("同期処理 {0}", i);
}
Console.WriteLine("同期処理の終了。");
Console.ReadLine();
}
// 非同期処理の関数
static void DoAsyncProc(Callback callback)
{
// 非同期処理
for (int i = 0; i < 4; i++)
{
Thread.Sleep(1000);
Console.WriteLine("非同期処理 {0}", i);
}
// Callback型のDelegate実行。非同期処理の実行結果(true固定)を渡す
callback(true);
}
// コールバック関数
static void DoCallBack(bool res)
{
Console.WriteLine("非同期処理の終了。res:{0}", res);
}
}
}
|
4:定義済みdelegateを利用する
delegate bool JudgeMethod(int num);の様にユーザが独自にdelegateを定義することも可能ですが、よく使用されるものは定義済みdelegateとして事前に用意されています。
ここではC#のFunc型変数を利用した例を示します。
Func型変数
Func型とは、任意のデータ型の戻り値があり0~16個の任意のデータ型の引数を持つことができるデリゲートです。
「条件判断処理を差し替える」のC#のサンプルコードは以下の様に修正できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
using System;
namespace CsDelegateFunc
{
class Program
{
static void Main(string[] args)
{
int[] ary = new int[] { 9, 3, 5, 2, 7, 8, 1, 6, 4 };
//aryの5より大きい値を表示する
// Func型として宣言している
Func<int, Boolean> func = JudgeOver5;
for (int i = 0; i < ary.Length; i++)
{
if (func(ary[i])) { Console.Write(ary[i] + " "); }
}
Console.WriteLine("");
//aryの5より小さい値を表示する
// Func型として宣言している
func = JudgeUnder5;
for (int i = 0; i < ary.Length; i++)
{
if (func(ary[i])) { Console.Write(ary[i] + " "); }
}
Console.ReadLine();
}
static bool JudgeOver5(int val) { return val > 5; }
static bool JudgeUnder5(int val) { return val < 5; }
}
}
|
上のサンプルプログラムを実行すると、以下のように表示されます。
1
2
|
9 7 8 6
3 2 1 4
|
C#のdelegateとあわせて覚えておきたいラムダ式
C#でFunc型変数を使用した場合、匿名メソッドを利用した場合とラムダ式を使用した場合の違いは以下の様になります。
Func型変数を使用した場合の例は以下になります。
・参照されるメソッド。
1
2
3
|
static bool JudgeOver5(int val) { return val > 5; }
|
・Func型変数の宣言
1
2
3
|
Func<int, Boolean> func = JudgeOver5;
|
匿名メソッドを利用したコードの例は以下になります。
1
2
3
|
JudgeMethod jm = delegate (int val) { return val > 5; };
|
ラムダ式を使用した場合の例は以下になります。
1
2
3
|
Func judge = val => val > 5;
|
メソッドを独立して定義する必要はなく、その場でメソッドの内容を記述します。
ラムダ式の使い方
「Func型変数」のC#のサンプルコードは以下の様に修正できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System;
namespace CsDelegateLambda
{
class Program
{
static void Main(string[] args)
{
int[] ary = new int[] { 9, 3, 5, 2, 7, 8, 1, 6, 4 };
// 値が5を超えるとtrueを返すラムダ式
Func<int, bool> judge = val => val > 5;
for (int i = 0; i < ary.Length; i++)
{
// ラムダ式judgeで判断
if (judge(ary[i])) { Console.Write(ary[i] + " "); }
}
Console.WriteLine("");
// 値が5を下回るとtrueを返すラムダ式
judge = val => val < 5;
for (int i = 0; i < ary.Length; i++)
{
// ラムダ式judgeで判断
if (judge(ary[i])) { Console.Write(ary[i] + " "); }
}
Console.ReadLine();
}
}
}
|
上のサンプルプログラムを実行すると、以下のように表示されます。
1
2
|
9 7 8 6
3 2 1 4
|
C#のdelegateを使ってみよう
ここまでC#でdelegateを使用する例を提示してきました。基本的な使い方から動的にメソッドを追加して連続処理を行ったり、動的に条件判断処理を変更する例などを示してきました。
delegateの委譲という考え方もC#の理解を深めるのに役立つので、是非マスターしてください。
FEnetを運営しているネプラス株式会社はサービス開始から10年以上
『エンジニアの生涯価値の向上』をミッションに掲げ、
多くのインフラエンジニア・ネットワークエンジニアの就業を支援してきました。
ネプラス株式会社はこんな会社です
秋葉原オフィスにはネプラス株式会社をはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
インフラ業界に特化
ネットワーク・サーバー・データベース等、ITインフラ業界に特化。Cisco Systemsプレミアパートナーをはじめ各種ベンダーのパートナー企業です。
業界を知り尽くしているからこそ大手の取引先企業、経験豊富なエンジニアに選ばれています。
-
正社員なのにフリーランスのような働き方
正社員の方でも希望を聞いたうえでプロジェクトをアサインさせていただいており、フリーランスのような働き方が可能。帰社日もありません。
プロジェクト終了後もすぐに次の案件をご紹介させていただきますのでご安心ください。
-
大手直取引の高額案件
案件のほとんどが大手SIerやエンドユーザーからの直取引のためエンジニアの皆様へに高く還元できています。
Ciscoをはじめ、Juniper、Azure、Linux、AWS等インフラに特化した常時300件以上の案件があります。
-
スキルアップ支援
不要なコストを削減し、その分エンジニアの方へのスキルアップ支援(ネットワーク機器貸出、合格時の受験費用支給など)や給与で還元しています。
受験費用例)CCNP,CCIE:6-20万円、JNCIS:3-4万円、AWS:1-3万円など
※業務に関連する一定の資格のみ。各種条件がありますので詳しくは担当者へにお尋ねください。
-
現給与を保証します!※
前職の給与保証しており、昨年度は100%の方が給与アップを実現。収入面の不安がある方でも安心して入社していただけます。
※適用にはインフラエンジニアの業務経験1年以上、等一定の条件がございます。
-
インセンティブ制度
ネットワーク機器の販売・レンタル事業等、売上に貢献いただいた方にはインセンティブをお支払いしています。
取引先企業とエンジニア側、双方にメリットがあり大変好評をいただいています。
-
社会保険・福利厚生
社員の方は、社会保険を完備。健康保険は業界内で最も評価の高い「関東ITソフトウェア健康保険組合」です。
さらに様々なサービスをお得に利用できるベネフィットステーションにも加入いただきます。
-
東証プライム上場企業グループ
ネプラスは東証プライム上場「株式会社夢真ビーネックスグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
ネプラス株式会社に興味を持った方へ
ネプラス株式会社では、インフラエンジニアを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
オンライン面接も随時受付中。ぜひお気軽にご応募ください。


C#新着案件New Job
-
【高額年収】/競馬場向け音声案内ツール運用保守/神奈川県横浜市/【WEB面談可/インフラサーバ経験者/20~40代の方活躍中】/在宅勤務
年収600万~720万円神奈川県横浜市(桜木町駅) -
【高額年収】/ECサイト運用保守/Windows/東京都23区東部/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収600万~720万円東京都23区東部(-駅) -
【高額年収】/共通基盤や製品に関わる運用保守/C#/東京都中野区/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収600万~720万円東京都中野区(中野駅) -
ECサイト構築/Windows/東京都23区東部/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収540万~720万円東京都23区東部(-駅) -
VR・AIサービス運用保守/C#/東京都品川区/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収600万~720万円東京都品川区(五反田駅) -
Web受付ツール及びサーバ運用保守/東京都千代田区/【WEB面談可/インフラサーバ経験者/20~40代の方活躍中】/在宅勤務
年収480万~660万円東京都千代田区(飯田橋駅)