Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#中,是否每次都对循环声明求值?_C#_Loops_For Loop_Conditional Statements_Evaluation - Fatal编程技术网

在C#中,是否每次都对循环声明求值?

在C#中,是否每次都对循环声明求值?,c#,loops,for-loop,conditional-statements,evaluation,C#,Loops,For Loop,Conditional Statements,Evaluation,这真是一个吹毛求疵的问题,但好奇心征服了我 for循环是否在每次执行循环时重新评估RHS条件?见下文 for(int i = 0; i < collection.Count; i++) { } for(int i=0;i

这真是一个吹毛求疵的问题,但好奇心征服了我

for循环是否在每次执行循环时重新评估RHS条件?见下文

for(int i = 0; i < collection.Count; i++)
{
}
for(int i=0;i
在整个代码库中执行以下操作是否是一种良好的实践

for(int i = 0, n = collections.Count; i < n; i++)
{
}
for(int i=0,n=collections.Count;i

或者编译器是否进行了此类优化/这些优化可以忽略不计(即使有庞大的代码库)?

在每次迭代之前都会重新评估该条件(除非编译器检测到该条件是常量),并且可以编写依赖于此的代码(例如调用返回值每次都不同的函数)因此,如果您有一个计算代价高昂的条件,并且您确信该条件将保持不变,那么在循环之前对其进行一次计算确实是一个好主意。但是,对于大多数标准集合类型而言,
Count
是一个如此快速的操作,以至于可以忽略不计的性能增益不值得降低可读性。

在每次迭代之前,将重新计算该条件(除非编译器检测到该条件为常量),并且可以编写依赖于该条件的代码(例如调用返回值每次都不同的函数)因此,如果您有一个评估成本很高的条件,并且您确信它将保持不变,那么在循环之前对其进行一次评估确实是一个好主意。但是,对于大多数标准集合类型而言,
Count
是一个非常快的操作,可以忽略不计的性能增益不值得降低可读性。

如果条件的ht是恒定的(因此它在循环内部不会改变),我相信优化器会移动集合。计数在循环顶部之外。如果集合在循环中被修改,则每次都会进行计算

如果使用foreach,您会注意到无法更改循环内的枚举数,因为foreach使用此优化来加快循环


你可以编写一个带有两个循环的小演示应用程序,一个在循环中修改,一个不修改,然后在其上运行ildasm,看看生成了什么代码。

如果条件的右边是常量(因此它在循环内部不会改变)我相信优化器会移动集合。计数在循环顶部之外。如果集合在循环中被修改,则每次都会进行计算

如果使用foreach,您会注意到无法更改循环内的枚举数,因为foreach使用此优化来加快循环



你可以编写一个带有两个循环的小演示应用程序,一个在循环中修改,一个不修改,然后在其上运行ildasm,看看生成了什么代码。

第二个循环没有编译。你是否错过了
;i
?为什么不改用
foreach
?这样就不用担心这些优化了。@FrédéricHamidi,因为您可能不想为每个元素做一些事情?@FédéricHamidi,因为您可能想对元素做一些事情index@MarcinJuraszek感谢您发现:)第二个循环无法编译。你错过了
;i?为什么不改用
foreach
?那么就不必担心这种优化了。@FrédéricHamidi,因为您可能不想为每个元素做些什么?@FrédéricHamidi,因为您可能想对index@MarcinJuraszek感谢您发现:)未指定
集合的类型。如果它被声明为
IEnumerable
,并包含对
ICollection或
ICollection
实现的引用,
Count`将有点慢;如果它被声明为
IEnumerable
,并且持有对某个特定泛型类型都没有实现的引用,即使它对从
t
派生的某些
U
实现了
IList
计数可能非常慢。@supercat:True;我对此做了澄清。@supercat如果它是一个
IEnumerable
,那么它将是
Count()
,而不是
Count
。虽然有可能拥有一个速度非常慢的房产,但这是非常不寻常的;最有可能的情况是,您需要一个自定义的集合类型,它只做了一些非常愚蠢的事情,速度慢到足以成为一个问题。@Servy:我错过了这个区别。即使有这种区别,类型实现
ICollection
这一事实并不意味着
Count
的读取速度与变量读取速度一样快。对于许多类型,它往往至少需要一个虚拟方法分派。此外,如果集合在枚举过程中可能追加了项,代码应该清楚循环是否应该包含这些项。@supercat Yes,正如我所说,自定义集合可能在
Count
方法中做各种各样的坏事,这可能会很慢;BCL集合类型不会这样做。尝试删除虚拟分派几乎肯定是一个不值得做的微优化,在枚举集合时对集合进行变异是一个非常糟糕的主意;无论如何都应该避免的事情。
集合的类型未指定。如果它被声明为
IEnumerable
,并包含对
ICollection或
ICollection
实现的引用,
Count`将有点慢;如果它被声明为
IEnumerable
,并且持有对某个特定泛型类型都没有实现的引用,即使它对从
t
派生的某些
U
实现了
IList
计数可能非常慢。@supercat:True;我对此做了澄清。@supercat如果它是一个
IEnumerable
,那么它将是
Count()
,而不是
Count