再帰呼出し ラムダで簡単に

基本用法
再帰呼出しは、メソッドの中からそのメソッド自身を呼び出す類の処理のことを言います。

階乗計算やフィボナッチ数列の例ばかりが見つかりますが、他にもいろいろと活躍の場が多い実装方式です。

ここではフォルダ内の全てのファイルパスをリスト化するサンプルで紹介します。

指定フォルダ内にある全ファイル名を取得するサンプルコード

特定のフォルダにあるファイルのリストはDirectoryInfoクラスのGetFilesメソッドで取得できます。
そのフォルダにあるサブフォルダのリストは同クラスのGetDirectoriesメソッドで取得できます。
GetFilesメソッドで取得したファイルを保持し、GetDirectoriesメソッドで取得したフォルダを起点として同処理を繰り返せば、サブフォルダのサブフォルダの・・・とすべて取得することができます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

    class Program
    {
        static void Main(string[] args)
        {
            string basePath = @"C:\TestFolder";

            var list = GetAllFilePathList(basePath);
        }

        static IList<string> GetAllFilePathList(string path)
        {
            var fileList = new List<string>();

            EnumurateFiles(path, fileList);

            return fileList;
        }

        private static void EnumurateFiles(string path, List<string> list)
        {
            DirectoryInfo dInfo = new DirectoryInfo(path);

            // フォルダ内の全ファイルをリストに追加
            dInfo.GetFiles().ToList().ForEach(fi => list.Add(fi.FullName));
            // 全サブフォルダを対象にこのメソッドをコール
            dInfo.GetDirectories().ToList().ForEach(di => EnumurateFiles(di.FullName, list));
        }

ラムダで置き換えたサンプルコード

上のサンプルコードでは受け口となるメソッドと、繰り返し処理となる部分のメソッドとの二段構えになっていました。
これはラムダで定義すれば一つで済みます。
ミソは自身のデリゲート(action)を未定義とさせないために一旦nullで初期化した後で定義しなおすことです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

    class Program
    {
        static void Main(string[] args)
        {
            string basePath = @"C:\TestFolder";

            var list = GetAllFilePathList(basePath);
        }

        static IList<string> GetAllFilePathList(string path)
        {
            List<string> fileList = new List<string>();

            Action<string, List<string>> action = null;
            action = (path, list) =>
            {
                DirectoryInfo dInfo = new DirectoryInfo(path);
                dInfo.GetFiles().ToList().ForEach(fi => list.Add(fi.FullName));
                dInfo.GetDirectories().ToList().ForEach(di => action(di.FullName, list));
            };

            action(path, fileList);

            return fileList;
        }
    }

その他

メソッドを呼ぶ毎にコールスタックが積まれるので可能となっています、案外簡単にStackOverFlowExceptionがスローされたりします。

そうでなくても処理が重かったりするとなかなか帰ってこなくなったりするので、使用する場合は充分なテストと場合によっては制限が必要だったりします。
基本用法
スポンサーリンク
C#プログラミング再入門