C#Linq扩展:for循环不可中断或继续
我最近实现了这个Linq扩展,用于自动测试。我知道我可以使用C#Linq扩展:for循环不可中断或继续,c#,linq,C#,Linq,我最近实现了这个Linq扩展,用于自动测试。我知道我可以使用来进行循环;然而,同样在iOS中工作,我喜欢你在使用方法代码时能像读英语句子一样阅读它们 /// <summary> /// Repeats an action x times /// </summary> /// <param name="times">The number of times an action should be repeated</param> /// <par
来进行循环;然而,同样在iOS中工作,我喜欢你在使用方法代码时能像读英语句子一样阅读它们
/// <summary>
/// Repeats an action x times
/// </summary>
/// <param name="times">The number of times an action should be repeated</param>
/// <param name="action">The action that should be repeated</param>
public static void DoIt(Int32 times, Action<Int32> action)
{
for (var i = 0; i < times; i++)
action(i);
}
可以清楚地理解为“使用当前索引i执行5次”。然而,现在我想在我的常规代码中也使用这个调用,我注意到我不能使用break代码>或继续代码>在DoIt
-块内
是否有可能使用现有语言支持的技术来转义Linq表达式?您可以稍微将操作
修改为谓词
:
缺点是块的最后一行必须始终包含返回false代码>。您可以将其视为询问“立即停止”的谓词
因此,总结一下:
return true; -> break
return false; -> continue
给孩子起个名字
我承认,解决方案不是很清晰:首先,使用布尔型语言有点混乱。但是,您可以通过引入枚举来解决此问题:
public enum LoopResult : byte {
Break = 1,
Continue = 0,
End = 0
}
End
实际上是Continue
的别名,但可以被视为更“自然”的表达方式,在这种情况下,可以使用函数重写DoIt
:
C#缺少预处理器/预编译器
但此外,将返回
部分放在代码中也不是很好的阅读方法。由于C#没有(标准)预编译器,因此我认为没有办法自动重写代码,这样就可以使用break
和continue
表达式。另一方面,预编译器会带来额外的麻烦,许多程序可能会因为预编译器太神奇而被破坏。您可以稍微将操作
修改为谓词
:
缺点是块的最后一行必须始终包含返回false代码>。您可以将其视为询问“立即停止”的谓词
因此,总结一下:
return true; -> break
return false; -> continue
给孩子起个名字
我承认,解决方案不是很清晰:首先,使用布尔型语言有点混乱。但是,您可以通过引入枚举来解决此问题:
public enum LoopResult : byte {
Break = 1,
Continue = 0,
End = 0
}
End
实际上是Continue
的别名,但可以被视为更“自然”的表达方式,在这种情况下,可以使用函数重写DoIt
:
C#缺少预处理器/预编译器
但此外,将返回
部分放在代码中也不是很好的阅读方法。由于C#没有(标准)预编译器,因此我认为没有办法自动重写代码,这样就可以使用break
和continue
表达式。另一方面,预编译器会带来额外的麻烦,许多程序可能会因为预编译器的魔力太大而崩溃。这是可行的。返回false以过早退出循环
public static void DoIt(Int32 times, Func<int, bool> action)
{
for (var i = 0; i < times; i++)
{
if (!action(i))
{
break;
}
}
Console.WriteLine("Done");
Console.ReadLine();
}
static void Main(string[] args)
{
DoIt(5, i =>
{
Console.WriteLine(i);
return i != 3; // returning false exits the loop
});
}
publicstaticvoiddoit(Int32次,Func动作)
{
对于(变量i=0;i<次;i++)
{
如果(!行动(i))
{
打破
}
}
控制台。写入线(“完成”);
Console.ReadLine();
}
静态void Main(字符串[]参数)
{
DoIt(5,i=>
{
控制台写入线(i);
return i!=3;//返回false退出循环
});
}
这样就行了。返回false以过早退出循环
public static void DoIt(Int32 times, Func<int, bool> action)
{
for (var i = 0; i < times; i++)
{
if (!action(i))
{
break;
}
}
Console.WriteLine("Done");
Console.ReadLine();
}
static void Main(string[] args)
{
DoIt(5, i =>
{
Console.WriteLine(i);
return i != 3; // returning false exits the loop
});
}
publicstaticvoiddoit(Int32次,Func动作)
{
对于(变量i=0;i<次;i++)
{
如果(!行动(i))
{
打破
}
}
控制台。写入线(“完成”);
Console.ReadLine();
}
静态void Main(字符串[]参数)
{
DoIt(5,i=>
{
控制台写入线(i);
return i!=3;//返回false退出循环
});
}
我倾向于通过以下方式修改DoIt
方法,使其更强大:
public static void DoIt<T>(
T initial, Func<T, bool> condition, Func<T, T> iterate, Action<T> action)
{
var t = initial;
while (condition(t))
{
action(t);
t = iterate(t);
}
}
甚至这个:
DoIt(
new { counter = 0, sum = 0 },
t => t.sum < 50,
t => new { counter = t.counter + 1, sum = t.sum + t.counter },
t =>
{
Console.WriteLine(t.counter);
Console.WriteLine(t.sum);
});
DoIt(
新的{counter=0,sum=0},
t=>t.sum<50,
t=>new{counter=t.counter+1,sum=t.sum+t.counter},
t=>
{
控制台写入线(t计数器);
控制台写入线(t.sum);
});
我倾向于通过以下方式修改DoIt
方法,使其更强大:
public static void DoIt<T>(
T initial, Func<T, bool> condition, Func<T, T> iterate, Action<T> action)
{
var t = initial;
while (condition(t))
{
action(t);
t = iterate(t);
}
}
甚至这个:
DoIt(
new { counter = 0, sum = 0 },
t => t.sum < 50,
t => new { counter = t.counter + 1, sum = t.sum + t.counter },
t =>
{
Console.WriteLine(t.counter);
Console.WriteLine(t.sum);
});
DoIt(
新的{counter=0,sum=0},
t=>t.sum<50,
t=>new{counter=t.counter+1,sum=t.sum+t.counter},
t=>
{
控制台写入线(t计数器);
控制台写入线(t.sum);
});
您可以使用返回继续。除非抛出异常(讨厌的),否则你不能真正地break
。我能想到的唯一解决方案是返回一个bool并根据它进行break。而且,DoIt(5,I=>Console.WriteLine(I))
与的(int i=0;iYes,我不想在这里抛出异常。Return可以工作,但我无法继续DoIt调用之后可能出现的代码。您可能最好还是习惯C语言的惯用代码。能够在语言及其样式之间切换是一项很好的技能。您可以使用Return
来继续除非你抛出一个异常(讨厌的)。我能想到的唯一解决办法就是返回一个bool并根据它进行中断。而且,DoIt(5,I=>Console.WriteLine(I))
看起来不像那样英语(int i=0;iYes,我不想在这里抛出异常。返回将起作用,但我无法继续DoIt调用之后可能出现的代码。您可能最好只是习惯C#惯用代码。能够在语言和它们的样式之间切换是一项很好的技能。感谢您为此所做的努力,但总的来说,这会带来很多问题更多c
DoIt(
new { counter = 0, sum = 0 },
t => t.sum < 50,
t => new { counter = t.counter + 1, sum = t.sum + t.counter },
t =>
{
Console.WriteLine(t.counter);
Console.WriteLine(t.sum);
});