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

时间:2022-04-15 21:39:25

In C#, using .NET Framework 4, is there an elegant way to repeat the same action a determined number of times? For example, instead of:

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

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

I would like to write something like:

我想写一些类似的东西:

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

toRepeat.Repeat(10);

or:

要么:

Enumerable.Repeat(10, () =>
{
    Console.WriteLine("Hello World.");
    this.DoSomeStuff();
});

I know I can create my own extension method for the first example, but isn't there an existent feature which makes it already possible to do this?

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

7 个解决方案

#1


23  

There is no built-in way to do this.

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

The reason is that C# as it is tries to enforce a divide between the functional and imperative sides of the language. C# only makes it easy to do functional programming when it is not going to produce side effects. Thus you get collection-manipulation methods like LINQ's Where, Select, etc., but you do not get ForEach.1

原因是C#试图强制在语言的功能和命令方面之间划分。只有C#才能在不产生副作用的情况下轻松进行函数式编程。因此,您可以获得LINQ的Where,Select等集合操作方法,但是您没有获得ForEach.1

In a similar way, what you are trying to do here is find some functional way of expressing what is essentially an imperative action. Although C# gives you the tools to do this, it does not try to make it easy for you, as doing so makes your code unclear and non-idiomatic.

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

1 There is a List<T>.ForEach, but not an IEnumerable<T>.ForEach. I would say the existence of List<T>.ForEach is a historical artifact stemming from the framework designers not having thought through these issues around the time of .NET 2.0; the need for a clear division only became apparent in 3.0.

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

#2


33  

Like this?

喜欢这个?

using System.Linq;

Enumerable.Range(0, 10).ForEach(arg => toRepeat());

This will execute your method 10 times.

这将执行您的方法10次。

[Edit]

[编辑]

I am so used to having ForEach extension method on Enumerable, that I forgot it is not part of FCL.

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

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

Here is what you can do without ForEach extension method:

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

Enumerable.Range(0, 10).ToList().ForEach(arg => toRepeat());

[Edit]

[编辑]

I think that the most elegant solution is to implement reusable method:

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

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

Usage:

用法:

RepeatAction(10, () => { Console.WriteLine("Hello World."); });

#3


7  

Without rolling out your own extension, I guess you can do something like this

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

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

    int repeat = 10;
    Enumerable.Range(0, repeat).ToList().ForEach(i => toRepeat());

#4


7  

For brevity of a one liner you could do this. Not sure what you think...

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

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

#5


1  

Table table = frame.AddTable();
int columnsCount = 7;

Enumerable.Repeat<Func<Column>>(table.AddColumn, columnsCount)
          .ToList()
          .ForEach(addColumn => addColumn());
//or
Enumerable.Range(0, columnsCount)
          .ToList()
          .ForEach(iteration => table.AddColumn());

these options are not elegant because of ToList(), but both worked in my case

由于ToList(),这些选项并不优雅,但两者都适用于我的情况

#6


0  

Declare an extension:

声明扩展名:

public static void Repeat(this Action action, int times){
    while (times-- > 0)
        action.Invoke();
}

You can use the extension method as:

您可以使用扩展方法:

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

#7


0  

Enumerable.Repeat<Action>(() => { Console.WriteLine("Hello World"); this.DoSomething(); },10);

elegant isn't it?

优雅不是吗?

#1


23  

There is no built-in way to do this.

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

The reason is that C# as it is tries to enforce a divide between the functional and imperative sides of the language. C# only makes it easy to do functional programming when it is not going to produce side effects. Thus you get collection-manipulation methods like LINQ's Where, Select, etc., but you do not get ForEach.1

原因是C#试图强制在语言的功能和命令方面之间划分。只有C#才能在不产生副作用的情况下轻松进行函数式编程。因此,您可以获得LINQ的Where,Select等集合操作方法,但是您没有获得ForEach.1

In a similar way, what you are trying to do here is find some functional way of expressing what is essentially an imperative action. Although C# gives you the tools to do this, it does not try to make it easy for you, as doing so makes your code unclear and non-idiomatic.

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

1 There is a List<T>.ForEach, but not an IEnumerable<T>.ForEach. I would say the existence of List<T>.ForEach is a historical artifact stemming from the framework designers not having thought through these issues around the time of .NET 2.0; the need for a clear division only became apparent in 3.0.

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

#2


33  

Like this?

喜欢这个?

using System.Linq;

Enumerable.Range(0, 10).ForEach(arg => toRepeat());

This will execute your method 10 times.

这将执行您的方法10次。

[Edit]

[编辑]

I am so used to having ForEach extension method on Enumerable, that I forgot it is not part of FCL.

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

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

Here is what you can do without ForEach extension method:

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

Enumerable.Range(0, 10).ToList().ForEach(arg => toRepeat());

[Edit]

[编辑]

I think that the most elegant solution is to implement reusable method:

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

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

Usage:

用法:

RepeatAction(10, () => { Console.WriteLine("Hello World."); });

#3


7  

Without rolling out your own extension, I guess you can do something like this

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

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

    int repeat = 10;
    Enumerable.Range(0, repeat).ToList().ForEach(i => toRepeat());

#4


7  

For brevity of a one liner you could do this. Not sure what you think...

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

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

#5


1  

Table table = frame.AddTable();
int columnsCount = 7;

Enumerable.Repeat<Func<Column>>(table.AddColumn, columnsCount)
          .ToList()
          .ForEach(addColumn => addColumn());
//or
Enumerable.Range(0, columnsCount)
          .ToList()
          .ForEach(iteration => table.AddColumn());

these options are not elegant because of ToList(), but both worked in my case

由于ToList(),这些选项并不优雅,但两者都适用于我的情况

#6


0  

Declare an extension:

声明扩展名:

public static void Repeat(this Action action, int times){
    while (times-- > 0)
        action.Invoke();
}

You can use the extension method as:

您可以使用扩展方法:

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

#7


0  

Enumerable.Repeat<Action>(() => { Console.WriteLine("Hello World"); this.DoSomething(); },10);

elegant isn't it?

优雅不是吗?