是否有一种优雅的方式来重复动作?

Ars*_*nko 39 .net c# linq .net-4.0

在C#中,使用.NET Framework 4,是否有一种优雅的方法可以重复执行相同的操作一定次数?例如,而不是:

int repeat = 10;
for (int i = 0; i < repeat; i++)
{
    Console.WriteLine("Hello World.");
    this.DoSomeStuff();
}
Run Code Online (Sandbox Code Playgroud)

我想写一些类似的东西:

Action toRepeat = () =>
{
    Console.WriteLine("Hello World.");
    this.DoSomeStuff();
};

toRepeat.Repeat(10);
Run Code Online (Sandbox Code Playgroud)

要么:

Enumerable.Repeat(10, () =>
{
    Console.WriteLine("Hello World.");
    this.DoSomeStuff();
});
Run Code Online (Sandbox Code Playgroud)

我知道我可以为第一个例子创建我自己的扩展方法,但是不存在一个现有的功能,这使得它已经可以做到这一点吗?

Ale*_*Aza 46

像这样?

using System.Linq;

Enumerable.Range(0, 10).ForEach(arg => toRepeat());
Run Code Online (Sandbox Code Playgroud)

这将执行您的方法10次.

[编辑]

我很习惯ForEach在Enumerable上使用扩展方法,我忘了它不是FCL的一部分.

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach (var item in source)
        action(item);
}
Run Code Online (Sandbox Code Playgroud)

如果没有ForEach扩展方法,您可以执行以下操作:

Enumerable.Range(0, 10).ToList().ForEach(arg => toRepeat());
Run Code Online (Sandbox Code Playgroud)

[编辑]

我认为最优雅的解决方案是实现可重用的方法:

public static void RepeatAction(int repeatCount, Action action)
{
    for (int i = 0; i < repeatCount; i++)
        action();
}
Run Code Online (Sandbox Code Playgroud)

用法:

RepeatAction(10, () => { Console.WriteLine("Hello World."); });
Run Code Online (Sandbox Code Playgroud)

  • 一个旧答案,但你也可以做'Enumerable.Range(0,10).选择(o =>/*返回或做某事*/) (2认同)

Dom*_*nic 24

没有内置的方法来做到这一点.

原因是C#试图强制在语言的功能和命令方面之间划分.C#只有在不产生副作用时才能轻松进行函数式编程.因此,你得收集,处理方法,如LINQ的Where,Select等等,但你没有得到ForEach.1

以类似的方式,你在这里尝试做的是找到一些表达本质上是命令行动的功能方式.虽然C#为您提供了执行此操作的工具,但它并不会让您感觉轻松,因为这样做会使您的代码不清晰且不具有惯用性.

1有一个List<T>.ForEach,但不是一个IEnumerable<T>.ForEach.我想说存在的List<T>.ForEach是一个历史的神器,源于框架设计者在.NET 2.0时代没有考虑过这些问题; 只有在3.0中才能明确划分明确的分工.

  • 当然,没有什么可以阻止你在IEnumerable上编写你自己的副作用"重复"或"ForEach"方法 - 语言设计师已经洗了他们的手. (5认同)
  • 我能问一下为什么以 `ForEach` 为例,这是一件坏事吗? (2认同)
  • @CodeBlend,这将是一个很好的问题。 (2认同)
  • @Domenic - 我认为你的解释是正确的,为什么LINQ没有帮助.但是,它并不适用于更广泛的问题,为什么C#缺乏一种*命令式的方式来说"重复循环n次".其他语言也这样做.或者至少接近这样做,比如VB的'For .. To ..`,它避免了C#测试的语义上的过度杀戮以及递增或递减循环变量,这是在逐步通过一系列值的常见情况下.我们坚持使用20世纪70年代为C发明的语法,因为它在DEC PDP-11上有效,后者具有递增和递减指令. (2认同)

小智 9

为了简化一个班轮你可以做到这一点.不确定你的想法......

Enumerable.Repeat<Action>(() => 
{
    Console.WriteLine("Hello World.");
    this.DoSomeStuff();
}, 10).ToList().ForEach(x => x());
Run Code Online (Sandbox Code Playgroud)

  • o认为这不优雅.这比简单的for语句更难以理解和更难理解. (4认同)

Bal*_*a R 7

如果没有推出自己的扩展,我想你可以做这样的事情

    Action toRepeat = () => {
        Console.WriteLine("Hello World.");
         this.DoSomeStuff();
    };

    int repeat = 10;
    Enumerable.Range(0, repeat).ToList().ForEach(i => toRepeat());
Run Code Online (Sandbox Code Playgroud)


Ali*_*yun 7

Enumerable.Repeat<Action>(() => { Console.WriteLine("Hello World"); this.DoSomething(); },10).ToList().ForEach(f => f.Invoke());
Run Code Online (Sandbox Code Playgroud)

优雅不是吗?

  • 非常:)应该是公认的答案 (2认同)