zoukankan      html  css  js  c++  java
  • 递归选取扩展方法(RecursionSelect)的新重载形式

    RecursionSelect是一个极其方便的扩展方法,使用它仅需少量代码即可完成递归操作,从而大大提升编码速度和质量,此扩展方法在我的代码中被高频使用,这是我之前提供过的一个范例:

    [TestMethod]
    public void TestMethod13()
    {
        //获取指定目录中所有包含子目录的目录集合
        var d = new DirectoryInfo(@"C:\Users\Public\Downloads");
        var c = d.RecursionSelect(f => f.GetDirectories(), f => f.GetDirectories().Length > 0);
        MessageBox.Show(c.Count().ToString());
    }

    此方法源于鹤冲天的这篇文章:http://www.cnblogs.com/ldp615/archive/2009/11/09/1599312.html

    我曾在我的这篇文章中分享过我自己的实现版本(即RecursionSelect):http://www.cnblogs.com/SkyD/archive/2010/01/15/1648178.html

    现在,我为其又追加了一点小小改进,通过新的重载形式方法,使其中的判断表达式可以用于中止递归,这样就变得更灵活许多。

    具体为:增加了一个布尔类型参数,名为“检验失败是否继续”,此前默认的执行方式都是“true”,即“即使判断失败也会继续下面的递归”,这样判断表达式仅能起到一个过滤作用(类似Linq中的where),而如果将其设为false,就能够在第一次失败时阻断后面的一切操作,这在很多情况下非常有用(比如获取有共同特征的连续的对象链)。

    现在的完整代码如下(新增的重载加粗显示):

    /// <summary>
    /// 循环所有子项,递归选取并返回所有后代项,针对IEnumerable
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionEachSelect<T>(this IEnumerable o, Func<T, IEnumerable<T>> 递归项选取表达式)
    {
        return RecursionEachSelect(o, 递归项选取表达式, null);
    }

    /// <summary>
    /// 循环所有子项,递归选取并返回所有后代项,针对IEnumerable
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionEachSelect<T>(this IEnumerable o, Func<T, IEnumerable<T>> 递归项选取表达式, Predicate<T> 检验表达式)
    {
        return RecursionEachSelect(o.Cast<T>(), 递归项选取表达式, 检验表达式);
    }

    /// <summary>
    /// 循环所有子项,递归选取并返回所有后代项,针对IEnumerable泛型形式
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionEachSelect<T>(this IEnumerable<T> o, Func<T, IEnumerable<T>> 递归项选取表达式)
    {
        return RecursionEachSelect(o, 递归项选取表达式, null);
    }

    /// <summary>
    /// 循环所有子项,递归选取并返回所有后代项,针对IEnumerable泛型形式
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionEachSelect<T>(this IEnumerable<T> o, Func<T, IEnumerable<T>> 递归项选取表达式, Predicate<T> 检验表达式)
    {
        return RecursionEachSelect(o, 递归项选取表达式, 检验表达式, true);
    }

    /// <summary>
    /// 循环所有子项,递归选取并返回所有后代项,针对IEnumerable泛型形式
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <param name="检验失败是否继续">指示表达式检验失败后是否继续递归选取接下来的项,在不指定此参数的重载形式中默认为true</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionEachSelect<T>(this IEnumerable<T> o, Func<T, IEnumerable<T>> 递归项选取表达式, Predicate<T> 检验表达式, bool 检验失败是否继续)
    {
        foreach (var f in o)
        {
            bool? b = 检验表达式 == null ? (bool?)null : 检验表达式(f);
            if (b == null || b.Value) yield return f;
            else if (!检验失败是否继续)
            {
                yield break;
            }
            foreach (var d in RecursionSelect(f, 递归项选取表达式, 检验表达式))
            {
                yield return d;
            }
        }
    }

    /// <summary>
    /// 递归选取并返回后代项
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionSelect<T>(this T o, Func<T, T> 递归项选取表达式)
    {
        return RecursionSelect(o, 递归项选取表达式, null);
    }

    /// <summary>
    /// 递归选取并返回后代项
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionSelect<T>(this T o, Func<T, T> 递归项选取表达式, Predicate<T> 检验表达式)
    {
        return RecursionSelect(o, 递归项选取表达式, 检验表达式, true);
    }

    /// <summary>
    /// 递归选取并返回后代项
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <param name="检验失败是否继续">指示表达式检验失败后是否继续递归选取接下来的项,在不指定此参数的重载形式中默认为true</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionSelect<T>(this T o, Func<T, T> 递归项选取表达式, Predicate<T> 检验表达式, bool 检验失败是否继续)
    {
        if (o == null) yield break;
        var f = 递归项选取表达式(o);
        bool? b = 检验表达式 == null ? (bool?)null : 检验表达式(f);
        if (b == null || b.Value) yield return f;
        else if (!检验失败是否继续)
        {
            yield break;
        }
        foreach (var d in RecursionSelect(f, 递归项选取表达式, 检验表达式, 检验失败是否继续))
        {
            yield return d;
        }
    }

    /// <summary>
    /// 递归选取并返回后代项
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionSelect<T>(this T o, Func<T, IEnumerable<T>> 递归项选取表达式)
    {
        return RecursionSelect(o, 递归项选取表达式, null);
    }

    /// <summary>
    /// 递归选取并返回后代项
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionSelect<T>(this T o, Func<T, IEnumerable<T>> 递归项选取表达式, Predicate<T> 检验表达式)
    {
        return RecursionSelect(o, 递归项选取表达式, 检验表达式, true);
    }

    /// <summary>
    /// 递归选取并返回后代项
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="递归项选取表达式">通过此表达式选取要返回的子项</param>
    /// <param name="检验表达式">対返回项进行检验,返回代入此表达式后表达式成立的项</param>
    /// <param name="检验失败是否继续">指示表达式检验失败后是否继续递归选取接下来的项,在不指定此参数的重载形式中默认为true</param>
    /// <returns>选取的子项</returns>
    public static IEnumerable<T> RecursionSelect<T>(this T o, Func<T, IEnumerable<T>> 递归项选取表达式, Predicate<T> 检验表达式, bool 检验失败是否继续)
    {
        foreach (var f in 递归项选取表达式(o))
        {
            bool? b = 检验表达式 == null ? (bool?)null : 检验表达式(f);
            if (b == null || b.Value) yield return f;
            else if (!检验失败是否继续)
            {
                yield break;
            }
            foreach (var d in RecursionSelect(f, 递归项选取表达式, 检验表达式))
            {
                yield return d;
            }
        }
    }

    下载

    本文的XPS版本:http://www.uushare.com/user/icesee/file/3504904

  • 相关阅读:
    CEF解决加载慢问题
    CEF之CefSettings设置locale
    Win32程序支持命令行参数的做法(转载)
    VC++实现程序重启的方法(转载)
    CEF之CefSettings设置日志等级
    libcurl开源库在Win32程序中使用下载文件显示进度条实例
    libcurl开源库在Win7 + VS2012环境下编译、配置详解 以及下载文件并显示下载进度 demo(转载)
    使用ShellExecute打开目标文件所在文件夹并选中目标文件
    linux下gimp的使用
    linux下的chm阅读器?
  • 原文地址:https://www.cnblogs.com/SkyD/p/1824248.html
Copyright © 2011-2022 走看看