Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C#

C#のデリゲートが分からない・・を解決!初心者向けになるべく分かり易く説明してみた

投稿日:2021年1月14日 更新日:

<目次>

(1) C#のデリゲートが分からない・・を解決!初心者向けになるべく分かり易く説明してみた
 (1-1) デリゲートとは?「関数へのポインタ」だけでは説明しきれない・・
 (1-2) デリゲートの用途
 (1-3) コールバック関数の実装手順(例)
 (1-4) コールバック関数サンプルプログラム

(1) C#のデリゲートが分からない・・を解決!初心者向けになるべく分かり易く説明してみた

(1-1) デリゲートとは?「関数へのポインタ」だけでは説明しきれない・・

良くある説明では「関数へのポインタ」と説明されていたりします。この言葉を素直に解釈するならデリゲートは「ポインタ」なので、ある関数の「アドレス」の情報を保持しているものになります。

(図111)良くある説明の直感的なイメージ

これを実際のプログラムに起こすと、例えば次のような記述になります(※デリゲートの本来の力を発揮していない例です)。

(サンプルプログラム1)
(※注)デリゲートの本来の力を発揮していない例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateTest
{
    class Program2
    {
        //②ある関数「LoopPointer」へのポインタとなるデリゲートの作成
        public delegate void LoopPrintPointer();
        static void Main(string[] args)
        {
            //③ポインタに関数のアドレスを代入
            LoopPrintPointer lpp = new LoopPrintPointer(LoopPrint);
            lpp.Invoke();

        }
        //①ある関数「LoopPrint」を定義
        static void LoopPrint()
        {
            //何かしらの処理
            Console.WriteLine("### Method invoked");
        }
    }
}

(図112)

結果として、ポインタ(LoopPrintPointer)伝いで関数(LoopPrint)にアクセスできたものの、これではメソッドを普通に呼び出す方が効率が良いので、余り良い例ではありません。
 
ではデリゲートはどのような場面で使えるのでしょうか?
 
そもそも「delegate」は辞書で引くと「(組織等の)代表、使節、派遣団員」のような意味があり、組織と組織を繋げる役割の人(使節など)のようなニュアンスです。
 
プログラミング的に言えば、例えばclassとclassとを繋げるような動きをする事になります。この最たる例が「コールバック関数」です。つまり、delegateの最たる用途は「コールバック関数」の実現です。
 

(1-2) デリゲートの用途

デリゲートは主に「イベント」や「コールバック関数」の実装に使われます。

「イベント」はユーザーのアクション(例:ボタン押下やマウスクリック等)。

「コールバック関数」というのは「ある関数の引数」として渡される別の関数の事を「コールバック関数」と呼んでいます。コールバック関数は呼び出し先の処理の中で実行(コールバック)され、処理の完結に寄与します。渡した先で再度呼ばれる挙動から「コールバック関数」と名が付いています。

目次にもどる

(1-3) コールバック関数の実装手順(例)

では、実際にコールバック関数をデリゲートを使って作成する例を見てみます。

まずは次のようなプログラムがあるとします。ポイントはクラスが2つ「Program」と「SampleClass」があり、最終的にはデリゲートを使って、Programクラスの中でSampleClassの処理状況をリアルタイムに取得するような動きを、コールバック関数を使って実現していきます。

(Before:初期状態⇒※これからdelegate関連の記述を追記します)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //SampleClassをインスタンス化
            SampleClass sc = new SampleClass();
            //メソッド実行
            sc.LoopPrint();
        }
    }
    public class SampleClass
    {
        //ある関数
        public void LoopPrint()
        {
            //何かしらの処理
            for (int i = 0; i < 5000; i++)
            {
                //何かしらの処理
            }
        }
    }
}

(図113)

目次にもどる

(1-4) コールバック関数サンプルプログラム

サンプルプログラムをご紹介する前に、追記するコードを理解しやすいよう、デリゲートの概念についてお伝えしたいと思います。

冒頭にもあったとおり、デリゲートはclassとclassを繋ぐ「使節」のような派遣とイメージする事が出来ると思います。

その例えで行くと、delegate型の変数定義(右上)は「使節の受け入れ枠」のようなイメージでしょうか。他クラスからの関数を受け入れる定義として、
delegate型の変数を定義しています。

そしてコールバック関数(右下)は「使節が来訪した際にお願いするタスク」のようなイメージでしょうか。引数にdelegate型(Callback callback)を受取り、そのデリゲート(ポインタ)が指す関数を実行します。

デリゲート(関数へのポインタ)に引き渡す関数自体(左中央)は「使節」のイメージでしょうか。実際に派遣される使節(メソッド)の定義です。

(図114)デリゲートの概念図

これらを踏まえて、上記のBeforeのプログラムにデリゲートに関する記述を追加したものが下記になります。

(After:デリゲート実装後)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateTest
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleClass sc = new SampleClass();
            //⑤関数実行時の引数に④の関数を与える
            sc.LoopPrint(Callback);
        }
        //④コールバック時に実行する関数の処理を定義します
        // ※例えるなら使節が派遣先で行う支援内容を定義する
        static void Callback(int i)
        {
            Console.WriteLine("Current counter is " + i);
        }
    }
    public class SampleClass
    {
        //①デリゲートの定義
        // ※例えるなら他組織(クラス)から送り込まれる使節
        public delegate void Callback(int i);
        //②引数にデリゲートを与えます
        public void LoopPrint(Callback callback)
        {
            //何かしらの処理
            for (int i = 0; i < 2000; i++)
            {
                //③デリゲートが参照する関数を呼び出します
                //(ここがコールバックに相当します)
                callback(i);
            }
        }
    }
}

(図115)実行結果

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-C#

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

ASP.NET MVC(C#)でHelloWorldする手順

<目次> (1) ASP.NET MVC(C#)でHelloWorldする手順  (1-1) プロジェクトの作成  (1-2) Controller(コントローラー)の作成  (1-3) Veiw(ビ …

C#で「CS0518: 定義済みの型 ‘System.Range’は定義、またはインポートされていません」エラーが出た時の原因と対処

  <目次> (1) C#で「CS0518: 定義済みの型 ‘System.Range’は定義、またはインポートされていません」エラーが出た時の原因と対処  (1-1 …

Visual Studioのプロジェクトを別ソリューションに移動する手順

  <目次> (1) Visual Studioのプロジェクトを別ソリューションに移動する手順  (1-1) プロジェクトを別ソリューションに移動する手順  (1-2) 参考①:「.cspr …

C#のvarとは?型を調べる方法や制約事項についてもご紹介

<目次> (1) C#のvarとは?型を調べる方法や制約事項についてもご紹介  (1-1) C#のvarとは?  (1-2) サンプルプログラム:varの基本動作確認#1  (1-3) サンプルプログ …

C#のスレッド(Thread)とは?概要やサンプルプログラムをご紹介

  <目次> (1) C#のスレッド(Thread)とは?概要やサンプルプログラムをご紹介  (1-1) 概要   (1-1-1) スレッドのライフライクルについて   (1-1-2) ma …

  • English (United States)
  • 日本語
Top