【问题标题】:How to roll my own Jagged Foreach?如何滚动我自己的锯齿状 Foreach?
【发布时间】:2016-12-29 05:56:20
【问题描述】:

我的应用程序经常迭代锯齿状数组。我试图实现类似 foreach 的功能,而不是到处都是显式的嵌套循环。

我最近的尝试是这样的:

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

namespace JaggedTest
{
    static class Global
    {
        // Does not work
        public static void ForEachJagged<T>(Array A, System.Linq.Expressions.Expression<Action<T>> F)
        {
            foreach (var Item in A)
            {
                if (Item is Array)
                {
                    ForEachJagged<T>((Array)Item, F);
                }
                else
                {
                    System.Linq.Expressions.InvocationExpression Invo =
                        System.Linq.Expressions.Expression.Invoke(F,
                        System.Linq.Expressions.Expression.Constant(Item));
                    Console.WriteLine(Invo.ToString());
                    // How to execute "Invo" ?
                }
            }
        }
    }

        class Program
        {
        static void Main(string[] args)
        {
            int[][] Foo = new int[3][] {
                  new int[] {1}
                 ,new int[] {2,3,4,5,6}
                 ,new int[] {7,8,9}
                };

            Global.ForEachJagged<int>(Foo, X => Console.Write(X.ToString() + " "));

        }
    }
}

此程序为 lambda 表达式生成预期的“ToString”调试输出,但我一直在尝试实际执行此表达式。执行作为函数参数传递的 lambda 表达式的正确方法是什么?

-- 编辑--

根据 Slava Utesinov 的反馈工作锯齿状的 foreach:

public static void ForEachJagged<T>(Array A, Action<T> F)
{
   foreach (var Item in A)
   {
      if (Item is Array)
      {
          ForEachJagged<T>((Array)Item, F);
      }
      else
      {
         F((T)Item);
      }
   }
}

【问题讨论】:

  • Expression&lt;Action&lt;T&gt;&gt; 的目的是什么。为什么不接受Action&lt;T&gt;?仅当您想将 lambda“传输”到其他层时,通常才需要使用表达式树,例如当您希望 C# 中的 LINQ Select 在数据库中作为 SQL SELECT 执行时。
  • @Martin,没有目的。我是 C# 新手,出轨了。

标签: c# linq lambda


【解决方案1】:

Compile 方法呢:

foreach (var Item in A)
{
    if (Item is Array)  
        ForEachJagged<T>((Array)Item, F);   
    else    
        F.Compile()((T)Item);   
}

【讨论】:

  • 谢谢斯拉瓦。这可行,但在我的实际应用程序中,与嵌套循环相比,JaggedForEach 太慢了。我想这种缓慢是由于 Compile() 造成的,但我不确定。
  • 而不是Expression&lt;Action&lt;T&gt;&gt;,只需要使用Action&lt;T&gt;,所以你需要在没有Compile的情况下调用F((T)Item)
【解决方案2】:

如果您真的对它只是一个 foreach 循环感到厌烦,您可以执行以下操作:

foreach (var item in arr.SelectMany(a => a))
{
    Console.Write(item.ToString() + " ");
}

但实际上,我只是建议您进行嵌套。试图让代码看起来更漂亮所花费的所有努力都是为了 A) 让代码在 看来更漂亮,B) 让代码运行得明显(如果不是明显变慢的话),或者 C) 两者兼而有之。

如果是缩进让你束手无策,你总是可以让它看起来像这样:

foreach (var nest in arr)
foreach (var item in nest)
{
    Console.Write(item.ToString() + " ");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    相关资源
    最近更新 更多