通常我们使用计数器执行类似for或while循环的操作:
for (int i = 0; i < 10; i++)
{
list.Add(GetRandomItem());
}
但有时你会混淆边界。你可以使用while循环,但如果你犯了一个错误,这个循环是无限的...
在Perl例如,我会使用更明显的
for(1..10){
list->add(getRandomItem());
}
是否有类似“doitXtimes(10){...}”的内容?
答案 0 :(得分:62)
您可以轻松编写自己的扩展方法:
public static void Times(this int count, Action action)
{
for (int i = 0; i < count; i++)
{
action();
}
}
然后你可以写:
10.Times(() => list.Add(GetRandomItem()));
我不确定我是否真的建议你做,但这是一个选择。虽然你可以使用Enumerable.Range
或Enumerable.Repeat
创建一个适当长度的懒惰序列,但我不相信框架中有类似的东西,这在某些情况下很有用。
从C#6开始,您仍然可以方便地访问静态方法而无需创建扩展方法,使用using static
指令进行导入。例如:
// Normally in a namespace, of course.
public class LoopUtilities
{
public static void Repeat(int count, Action action)
{
for (int i = 0; i < count; i++)
{
action();
}
}
}
然后当你想要使用它时:
using static LoopUtilities;
// Class declaration etc, then:
Repeat(5, () => Console.WriteLine("Hello."));
答案 1 :(得分:40)
foreach (var i in Enumerable.Range(0, N))
{
// do something
}
答案 2 :(得分:33)
可以创建IEnumerable
Int32:
Enumerable.Range(0, 10);
ForEach扩展方法也广为人知(尽管未附带.NET)。你可以将两者结合起来:
Enumerable.Range(0, 10).ForEach(index => ...);
所以你的例子会变成:
Enumerable.Range(0, 10).ForEach(_ => list.Add(GetRandomItem()));
答案 3 :(得分:11)
我看到Jon Skeet beat me to it,但是此变体将允许您在每次运行时将索引传递给Action:
public static class IntegerExtensions
{
public static void TimesWithIndex(this int count, Action<int> action)
{
for (int i = 0; i < count; i++)
action(i);
}
}
并称之为:
10.TimesWithIndex((i) =>
obj[i].DoSomething());
答案 4 :(得分:4)
示例1
var loop = new Loop(50);
foreach(var index loop) {
// do something
}
示例2
foreach(var index in 50.Times().Start(1).Step(-1)) {
// do something
}
示例3
var loop = 20.Times();
while (loop.Do) {
// do something
}
Loop class&amp;扩展
public class Loop : IEnumerable<int> {
readonly int times = 0;
int start = 0;
int step = 1;
IEnumerator<int> e;
public Loop (int times, int start = 0, int step = 1) {
this.times = times < 0? 0-times : times;
this.start = start;
this.step = step;
}
public Loop Start(int value) {
this.start = value;
return this;
}
public Loop Step(int value) {
this.step = value;
return this;
}
public bool Do {
get {
if (this.e.IsNull()) {
this.e = this.GetEnumerator();
}
if (this.e.MoveNext()) {
return true;
}
else {
this.e.Dispose();
this.e = null;
return false;
}
}
}
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
public IEnumerator<int> GetEnumerator() {
int count = times;
int value = start;
while (count != 0) {
yield return value;
try {
value += step;
}
catch (OverflowException) {
break;
}
--count;
}
yield break;
}
}
public static class IntLoopExtension {
public static Loop Times (this int self) {
return new Loop (self);
}
}
答案 5 :(得分:2)
while (i-- > 0) {
}
你提到虽然循环是危险的,因为它可能是无限的 - 上面的形式非常简单,永远不会是无限的。至少完全无限:)
它方便而短(比任何其他答案都短)并且将完全 i 次运行(因为postfix减量在递减之前返回值)。
答案 6 :(得分:2)
仍然缺少一种方法:
List<T> list = System.Linq.Enumerable.Range(0, 10).Select(_ => GetRandomItem()).ToList();
其中T是GetRandomItem()返回的类型