假设我有一些看起来像这样的代码:
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
}
}
答案 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);
}
}