プログラミングを試してみたい人向けのC#プログラミングチュートリアル

メソッド変数(delegate,Action,Func,ラムダ式)の使い方

POINT
  • メソッドを変数ように受け渡しする方法を説明
  • delegate, Action, Funcの使い方を説明
  • ラムダ式の使い方を説明
目次

delegateの使い方

delegateはメソッドを型として定義できる仕組みです。
定義しておくことでメソッドを変数のように受け渡しができるようになります。

使用例
    // メソッドの型定義
    public delegate void MessageMethod(string message);
    
    // メソッドの型を使用して引数として使用
    public void CallMessageMethod(MessageMethod method)
    {
        ・・・
    }

サンプルプログラムをご紹介します。
次のファイルを同じフォルダに作成してください。

ファイル名:Program.cs
public class Program
{
    public static void Main()
    {
        MessageManager messageManager = new MessageManager();

        // メソッドを渡して処理実行
        messageManager.CallMessageMethod(ShowMessage);
    
        // キー入力待ち
        System.Console.ReadKey();
    }
    
    /// 呼び出してもらうメソッドを用意
    private static void ShowMessage(string message)
    {
        System.Console.WriteLine(message);
    }
}

/// メッセージ管理クラス
public class MessageManager
{
    string[] messageList = { "あいうえお", "かきくけこ", "さしすせそ" };
    
    // メソッドの型定義
    public delegate void MessageMethod(string message);
    

    /// メッセージごとメソッド呼び出しするメソッド
    public void CallMessageMethod(MessageMethod method)
    {
        foreach (string message in messageList)
        {
            // 引数で渡されたメソッドを呼び出し
            method(message);
        }
    }

}
ファイル名:Compile.bat
C:¥Windows¥Microsoft.NET¥Framework¥v4.0.30319¥csc.exe *.cs
pause
Program.exe 実行結果
あいうえお
かきくけこ
さしすせそ

ファイルを作成できたらCompile.batを実行してみましょう。
同じフォルダにProgram.exeが作成されます。
Program.exeを実行して「Program.exe 実行結果」のように表示されたら成功です。

Program.cs(抜粋)
    public delegate void MessageMethod(string message);

この部分が型定義です。
MessageManagerクラスでは、次のように引数として定義したdelegate型であるMessageMethodを受け取れるようにしています。

Program.cs(抜粋)
    public void CallMessageMethod(MessageMethod method)

Programクラスではdelegate MessageMethodと同じ型のメソッドShowMessageを用意しています。

Program.cs(抜粋)
    private static void ShowMessage(string message)

delegateの型とあっていれば、次のようにメソッドを引数として渡せます。

Program.cs(抜粋)
        messageManager.CallMessageMethod(ShowMessage);

MessageManagerクラスのCallMessageMethodでは、引数methodを呼び出すことで元々渡されたProgramクラスのShowMessageが実行されます。

Program.cs(抜粋)
            method(message);

こうすることで疎結合を保ちながら、一部処理は呼出し元で処理ができるようになります。

Actionの使い方

Actionは、delegateのように定義なしに戻り値なしのメソッドを変数のように扱えるようにします。
戻り値ありの場合は後述するFuncを使用します。

使用例
    public void CallMessageMethod(System.Action<string> action)

delegateで型を定義することなく、上記のように記載することでメソッドの型を表しています。
Action<string>の<>の中が扱うメソッドの引数の型になります。
複数の引数がある場合はAction<string, string>のようにカンマ区切りで指定します。
delegateの定義が不要な分、手軽に使用することができます。

サンプルプログラムをご紹介します。
delegateの説明の際に作成したProgram.csを下記のように変更して保存してください。

ファイル名:Program.cs
public class Program
{
    public static void Main()
    {
        MessageManager messageManager = new MessageManager();
        
        // メソッドを渡して処理実行
        messageManager.CallMessageMethod(ShowMessage);
    
        // キー入力待ち
        System.Console.ReadKey();
    }
    
    /// 呼び出してもらうメソッドを用意
    private static void ShowMessage(string message)
    {
        System.Console.WriteLine(message);
    }
}

/// メッセージ管理クラス
public class MessageManager
{
    string[] messageList = { "あいうえお", "かきくけこ", "さしすせそ" };
        
    /// メッセージごとメソッド呼び出しするメソッド
    public void CallMessageMethod(System.Action<string> action)
    {
        foreach (string message in messageList)
        {
            // 引数で渡されたメソッドを呼び出し
            action(message);
        }
    }

}

ファイルを保存したらCompile.batを実行してみましょう。
同じフォルダにProgram.exeが作成されます。
Program.exeを実行してdelegateの「Program.exe 実行結果」と同じように表示されたら成功です。

Funcの使い方

Actionは戻り値なしでしたが、戻り値ありの場合に使用するのがFuncです。

使用例
    public void CallMessageMethod(System.Func<string, bool> func)

Func<string, bool>の<>の中の一つ目が戻り値の型、二つ目以降が引数になります。
複数の引数がある場合はAction<string, bool, string>のようにさらにカンマ区切りで追加していきます。

サンプルプログラムをご紹介します。
delegateの説明の際に作成したProgram.csを下記のように変更して保存してください。

ファイル名:Program.cs
public class Program
{
    public static void Main()
    {
        MessageManager messageManager = new MessageManager();
        
        // メソッドを渡して処理実行
        messageManager.CallMessageMethod(ShowMessage);
    
        // キー入力待ち
        System.Console.ReadKey();
    }
    
    /// 呼び出してもらうメソッドを用意
    private static bool ShowMessage(string message)
    {
        if (string.IsNullOrEmpty(message))
        {
            return false;
        }
        System.Console.WriteLine(message);
        return true;
    }
}

/// メッセージ管理クラス
public class MessageManager
{
    string[] messageList = { "あいうえお", "かきくけこ", "", "さしすせそ" };
        
    /// メッセージごとメソッド呼び出しするメソッド
    public void CallMessageMethod(System.Func<string, bool> func)
    {
        foreach (string message in messageList)
        {
            // 引数で渡されたメソッドを呼び出し
            if (!func(message))
            {
                // 戻り値がfalseの場合、処理終了
                break;
            }
        }
    }

}
Program.exe 実行結果
あいうえお
かきくけこ

ファイルを保存したらCompile.batを実行してみましょう。
同じフォルダにProgram.exeが作成されます。
Program.exeを実行して「Program.exe 実行結果」と同じように表示されたら成功です。

ラムダ式の使い方

ラムダ式はさらに呼出し元でメソッドを用意することなく、処理内容を直接記載して扱うことができる方法です。

Action使用例
    -- 呼出される側
    public void CallMessageMethod(System.Action<string> action)
    {
       ・・・
    }
    
    -- 呼出す側
    CallMessageMethod((string message) => 
    {
        System.Console.WriteLine(message);
    });
Func使用例
    -- 呼出される側
    public void CallMessageMethod(System.Func<string, bool> func)
    {
       ・・・
    }
    
    -- 呼出す側
    CallMessageMethod((string message) =>
    {
        if (string.IsNullOrEmpty(message))
        {
            return false;
        }
        System.Console.WriteLine(message);
        return true;
    });

次のように記載することで、処理の内容をそのままActionに渡すことができます。
Funcに渡すときはreturnで戻り値を返す処理を含めるようにします。

記載方法
(引数) => {処理内容}

Actionの場合のラムダ式使用サンプルです。

ファイル名:Program.cs
public class Program
{
    public static void Main()
    {
        MessageManager messageManager = new MessageManager();
        
        // ラムダ式で処理を渡して処理実行
        messageManager.CallMessageMethod((string message) =>
        {
            System.Console.WriteLine(message);
        });
        
        // actionを用意して渡す場合
        System.Action<string> action = (string message) =>
        {
            System.Console.WriteLine(message);
        };
        messageManager.CallMessageMethod(action);
    
        // キー入力待ち
        System.Console.ReadKey();
    }
}

/// メッセージ管理クラス
public class MessageManager
{
    string[] messageList = { "あいうえお", "かきくけこ", "さしすせそ" };
        
    /// メッセージごとメソッド呼び出しするメソッド
    public void CallMessageMethod(System.Action<string> action)
    {
        foreach (string message in messageList)
        {
            // 引数で渡されたメソッドを呼び出し
            action(message);
        }
    }

}

Funcの場合のラムダ式使用サンプルです。

ファイル名:Program.cs
public class Program
{
    public static void Main()
    {
        MessageManager messageManager = new MessageManager();
        
        // ラムダ式で処理を渡して処理実行
        messageManager.CallMessageMethod((string message) =>
        {
            if (string.IsNullOrEmpty(message))
            {
                return false;
            }
            System.Console.WriteLine(message);
            return true;
        });

        // Funcを用意して渡す場合
        System.Func<string, bool> func = (string message) =>
        {
            if (string.IsNullOrEmpty(message))
            {
                return false;
            }
            System.Console.WriteLine(message);
            return true;
        };
        messageManager.CallMessageMethod(func);

        // キー入力待ち
        System.Console.ReadKey();
    }
}

/// メッセージ管理クラス
public class MessageManager
{
    string[] messageList = { "あいうえお", "かきくけこ", "", "さしすせそ" };
        
    /// メッセージごとメソッド呼び出しするメソッド
    public void CallMessageMethod(System.Func<string, bool> func)
    {
        foreach (string message in messageList)
        {
            // 引数で渡されたメソッドを呼び出し
            if (!func(message))
            {
                // 戻り値がfalseの場合、処理終了
                break;
            }
        }
    }

}