C# Enumerable.Range 与传统 for 循环对 foreach 的思考
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/915745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Thoughts on foreach with Enumerable.Range vs traditional for loop
提问by Marcel Lamothe
In C# 3.0, I'm liking this style:
在 C# 3.0 中,我喜欢这种风格:
// Write the numbers 1 thru 7
foreach (int index in Enumerable.Range( 1, 7 ))
{
Console.WriteLine(index);
}
over the traditional for
loop:
在传统for
循环上:
// Write the numbers 1 thru 7
for (int index = 1; index <= 7; index++)
{
Console.WriteLine( index );
}
Assuming 'n' is small so performance is not an issue, does anyone object to the new style over the traditional style?
假设'n'很小所以性能不是问题,那么有人反对传统风格的新风格吗?
采纳答案by mqp
I find the latter's "minimum-to-maximum" format a lot clearer than Range
's "minimum-count" style for this purpose. Also, I don't think it's really a good practice to make a change like this from the norm that is not faster, not shorter, not more familiar, and not obviously clearer.
为此,我发现后者的“最小到最大”格式比Range
“最小计数”样式清晰得多。此外,我认为从不更快、不短、不更熟悉且不明显更清晰的规范中做出这样的改变并不是一个很好的做法。
That said, I'm not against the idea in general. If you came up to me with syntax that looked something like foreach (int x from 1 to 8)
then I'd probably agree that that would be an improvement over a for
loop. However, Enumerable.Range
is pretty clunky.
也就是说,我并不反对这个想法。如果你向我提出看起来像这样的语法,foreach (int x from 1 to 8)
那么我可能会同意这将是对for
循环的改进。然而,Enumerable.Range
相当笨重。
回答by TheTXI
I'm sure everybody has their personal preferences (many would prefer the later just because it is familiar over almost all programming languages), but I am like you and starting to like the foreach more and more, especially now that you can define a range.
我相信每个人都有自己的偏好(很多人更喜欢后者,因为它几乎在所有编程语言中都很熟悉),但我和你一样,开始越来越喜欢 foreach,尤其是现在你可以定义一个范围.
回答by spender
It seems like quite a long winded approach to a problem that's already solved. There's a whole state machine behind the Enumerable.Range
that isn't really needed.
对于已经解决的问题,这似乎是一种冗长的方法。背后有一个完全Enumerable.Range
不需要的状态机。
The traditional format is fundamental to development and familiar to all. I don't really see any advantage to your new style.
传统格式是发展的基础,并且为所有人所熟悉。我真的看不出你的新风格有什么好处。
回答by jerryjvl
I imagine there could be scenarios where Enumerable.Range(index, count)
is clearer when dealing with expressions for the parameters, especially if some of the values in that expression are altered within the loop. In the case of for
the expression would be evaluated based on the state after the current iteration, whereas Enumerable.Range()
is evaluated up-front.
我想Enumerable.Range(index, count)
在处理参数表达式时可能会有更清晰的场景,特别是如果该表达式中的某些值在循环中发生了改变。在for
表达式的情况下,将根据当前迭代后的状态进行评估,而预先评估Enumerable.Range()
。
Other than that, I'd agree that sticking with for
would normally be better (more familiar/readable to more people... readable is a very important value in code that needs to be maintained).
除此之外,我同意坚持使用for
通常会更好(对更多人来说更熟悉/可读......可读性是需要维护的代码中的一个非常重要的价值)。
回答by Dustin Campbell
I agree that in many (or even most cases) foreach
is much more readable than a standard for
-loop when simply iterating over a collection. However, your choice of using Enumerable.Range(index, count)
isn't a strong example of the value of foreach
over for.
我同意在许多(甚至大多数情况下)在简单地迭代集合时foreach
比标准for
循环更具可读性。但是,您选择使用Enumerable.Range(index, count)
并不是foreach
over for值的一个很好的例子。
For a simple range starting from 1, Enumerable.Range(index, count)
looks quite readable. However, if the range starts with a different index, it becomes less readable because you have to properly perform index + count - 1
to determine what the last element will be. For example…
对于从1, Enumerable.Range(index, count)
看起来很可读的简单范围开始。但是,如果范围以不同的索引开始,它的可读性就会降低,因为您必须正确执行index + count - 1
以确定最后一个元素是什么。例如…
// Write the numbers 2 thru 8
foreach (var index in Enumerable.Range( 2, 7 ))
{
Console.WriteLine(index);
}
In this case, I much prefer the second example.
在这种情况下,我更喜欢第二个例子。
// Write the numbers 2 thru 8
for (int index = 2; index <= 8; index++)
{
Console.WriteLine(index);
}
回答by fortran
I think the foreach + Enumerable.Range is less error prone (you have less control and less ways to do it wrong, like decreasing the index inside the body so the loop would never end, etc.)
我认为 foreach + Enumerable.Range 不太容易出错(你有更少的控制和更少的方法来做错,比如减少身体内部的索引,这样循环就永远不会结束,等等)
The readability problem is about the Range function semantics, that can change from one language to another (e.g if given just one parameter will it begin from 0 or 1, or is the end included or excluded or is the second parameter a count instead a end value).
可读性问题与 Range 函数语义有关,它可以从一种语言更改为另一种语言(例如,如果只给定一个参数,它将从 0 或 1 开始,或者包含或排除结尾,或者第二个参数是计数而不是结尾价值)。
About the performance, I think the compiler should be smart enough to optimize both loops so they execute at a similar speed, even with large ranges (I suppose that Range does not create a collection, but of course an iterator).
关于性能,我认为编译器应该足够聪明,可以优化两个循环,以便它们以相似的速度执行,即使范围很大(我认为 Range 不会创建集合,但当然是迭代器)。
回答by xyz
I do like the foreach
+ Enumerable.Range
approach and use it sometimes.
我确实喜欢foreach
+Enumerable.Range
方法并且有时会使用它。
// does anyone object to the new style over the traditional style?
foreach (var index in Enumerable.Range(1, 7))
I object to the var
abuse in your proposal. I appreciate var
, but, damn, just write int
in this case! ;-)
我反对var
你的建议中的滥用。我很感激var
,但是,该死的,就int
在这种情况下写吧!;-)
回答by LukeH
This is just for fun. (I'd just use the standard "for (int i = 1; i <= 10; i++)
" loop format myself.)
这只是为了好玩。(我自己只是使用标准的“ for (int i = 1; i <= 10; i++)
”循环格式。)
foreach (int i in 1.To(10))
{
Console.WriteLine(i); // 1,2,3,4,5,6,7,8,9,10
}
// ...
public static IEnumerable<int> To(this int from, int to)
{
if (from < to)
{
while (from <= to)
{
yield return from++;
}
}
else
{
while (from >= to)
{
yield return from--;
}
}
}
You could also add a Step
extension method too:
你也可以添加一个Step
扩展方法:
foreach (int i in 5.To(-9).Step(2))
{
Console.WriteLine(i); // 5,3,1,-1,-3,-5,-7,-9
}
// ...
public static IEnumerable<T> Step<T>(this IEnumerable<T> source, int step)
{
if (step == 0)
{
throw new ArgumentOutOfRangeException("step", "Param cannot be zero.");
}
return source.Where((x, i) => (i % step) == 0);
}
回答by THX-1138
You can actually do this in C# (by providing To
and Do
as extension methods on int
and IEnumerable<T>
respectively):
实际上,你可以做到这一点在C#中(通过提供To
与Do
作为扩展方法int
,并IEnumerable<T>
分别对应)。
1.To(7).Do(Console.WriteLine);
SmallTalk forever!
SmallTalk 永远!
回答by buti-oxa
Strictly speaking, you misuse enumeration.
严格来说,你滥用了枚举。
Enumerator provides the means to access all the objects in a container one-by-one, but it does not guarantee the order.
Enumerator 提供了对一个容器中的所有对象进行一一访问的方法,但它不保证顺序。
It is OK to use enumeration to find the biggest number in an array. If you are using it to find, say, first non-zero element, you are relying on the implementation detail you should not know about. In your example, the order seems to be important to you.
使用枚举查找数组中最大的数是可以的。如果您使用它来查找第一个非零元素,那么您将依赖于您不应该知道的实现细节。在您的示例中,订单似乎对您很重要。
Edit: I am wrong. As Luke pointed out (see comments) it is safe to rely on the order when enumerating an array in C#. This is different from, for example, using "for in" for enumerating an array in Javascript .
编辑:我错了。正如 Luke 指出的(见评论),在 C# 中枚举数组时依赖顺序是安全的。例如,这与在 Javascript 中使用“for in”枚举数组不同。