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
#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
#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?
优雅不是吗?