C#代码简化查询:顺序Foreach循环

时间:2009-03-20 16:14:12

标签: c#

假设我有一些看起来像这样的代码:

foreach(type x in list y)
{
   //dostuff1(x)
}

foreach(type x in list y)
{
   //dostuff2(x)
}

foreach(type x in list y)
{
   //dostuff3(x)
}

foreach(type x in list y)
{
   //dostuff4(x)
}

foreach(type x in list y)
{
   //dostuff5(x)
}

我无法将事物组合成一个大的for循环:

foreach (type x in list y)
{
    //dostuff1(x)
    //dostuff2(x)
    //dostuff3(x)
    //dostuff4(x)
    //dostuff5(x)
}

这样做会改变顺序。关于在C#中使代码更简单的最佳方法的任何评论?

我想我可以通过创建这样的函数来解决这个问题,不过我宁愿保持原样而不是强迫我的代码的未来读者理解yield

void func(type x)
{
    dostuff1(x)
    yield 0;
    dostuff2(x)
    yield 0;
    dostuff3(x)
    yield 0;
    dostuff4(x)
    yield 0;
    dostuff5(x)
    yield break;
}

for (int i = 0; i<5; ++i)
{
   foreach (type x in list y)
   {
       //Call func(x) using yield semantics, which I'm not going to look up right now
   }
}

6 个答案:

答案 0 :(得分:30)

另一种选择:

List<Action<Foo>> actions = new List<Action<Foo>> { 
    doStuff1, doStuff2, doStuff3, doStuff4, doStuff5
};

foreach (Action<Foo> action in actions)
{
    foreach (Foo x in list)
    {
        action(x);
    }
}

刚检查过,那就行了。例如:

using System;
using System.Collections.Generic;

public class Test
{
    static void Main(string[] args)
    {
        var actions = new List<Action<string>> {
            First, Second
        };

        foreach (var action in actions)
        {
            foreach (string arg in args)
            {
                action(arg);
            }
        }
    }

    static void First(string x)
    {
        Console.WriteLine("First: " + x);
    }

    static void Second(string x)
    {
        Console.WriteLine("Second: " + x);
    }
}

运行Test.exe a b c

的结果
First: a
First: b
First: c
Second: a
Second: b
Second: c

答案 1 :(得分:5)

如果你有一个相当稳定的动作列表,你可以避免使用foreach循环,但仍然明确地执行动作(没有测试代码):

list.ForEach(action1);
list.ForEach(action2);
list.ForEach(action3);
list.ForEach(action4);

答案 2 :(得分:5)

Jon Skeet的答案很棒(我刚刚投了票)。这是一个进一步发展的想法:

如果你做了很多,你可以做一个名为“DoActionsInOrder”的扩展方法(或者你可以想出一个更好的名字)。这是个主意:

public static void DoActionsInOrder<T>(this IEnumerable<T> stream, params Action<T> actionList)
{
     foreach(var action in actionList)
     {
          foreach(var item in stream)
          {
               action(item);
          }
     }
}

然后,您可以这样称呼它:

myList.DoActionsInOrder(doStuff1, doStuff2, doStuff3, doStuff4, doStuff5);

答案 3 :(得分:2)

怎么样:

interface IDoStuff
{
     void DoStuff(x);
}

List<IDoStuff> listOfActions = ...
foreach (IDoStuff iDoStuff in listOfActions)
{
    foreach (type x in list y)
    {
         iDoStuff(x);
    }
} 

[edit] 是的,您应该像J.Skeet所说的那样去寻找通用解决方案(尽管您也可以使用通用接口代替委托)。

答案 4 :(得分:0)

如果你必须保持连续性,那么你无能为力。你可以做一些扩展方法快捷方式,但恕我直言,这使得代码不太可读。此外,根据您的方法签名,您可能会遇到问题。

您可以重构以将迭代移动到单独的函数。

// Method 1
DoStuff1ToList(y);
DoStuff2ToList(y);
DoStuff3ToList(y);
DoStuff4ToList(y);
DoStuff5ToList(y);

// Do Stuff 1
foreach (var x in y)
{ 
    // do actual stuff
}

答案 5 :(得分:0)

我认为这与testing.ForEach(action)相同  所以如果你沿着这条路走下去就这么说吧。

private static void DoDifferentStuffToThings()
    {
        List<string> testing = new List<string>() { "hello", "world" };

        Action<string> action1 = (a) =>
        {
            Console.WriteLine("Action 1 {0}", a);
        };

        Action<string> action2 = (a) =>
        {
            Console.WriteLine("Action 2 {0}", a);
        };

        DoStuffToThings<string>(testing, action1);
        DoStuffToThings<string>(testing, action2);
    }

    private static void DoStuffToThings<T>(IEnumerable<T> list, Action<T> dothing)
        where T : class
    {
        foreach (var item in list)
        {
            dothing(item);
        }
    }