Cui*_*崔鹏飞 21 .net c# performance foreach value-type
在.NET中,使用"foreach"迭代IEnumerable的实例会创建一个副本吗?那么我是否应该使用"for"而不是"foreach"?
我写了一些代码来证明这一点:
struct ValueTypeWithOneField
{
private Int64 field1;
}
struct ValueTypeWithFiveField
{
private Int64 field1;
private Int64 field2;
private Int64 field3;
private Int64 field4;
private Int64 field5;
}
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("one field");
Test<ValueTypeWithOneField>();
Console.WriteLine("-----------");
Console.WriteLine("Five field");
Test<ValueTypeWithFiveField>();
Console.ReadLine();
}
static void Test<T>()
{
var test = new List<T>();
for (int i = 0; i < 5000000; i++)
{
test.Add(default(T));
}
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 5; i++)
{
sw.Start();
foreach (var item in test)
{
}
sw.Stop();
Console.WriteLine("foreach " + sw.ElapsedMilliseconds);
sw.Restart();
for (int j = 0; j < test.Count; j++)
{
T temp = test[j];
}
sw.Stop();
Console.WriteLine("for " + sw.ElapsedMilliseconds);
sw.Reset();
}
}}
Run Code Online (Sandbox Code Playgroud)
这是我运行代码后得到的结果:
one field
foreach 68
for 72
foreach 68
for 72
foreach 67
for 72
foreach 64
for 73
foreach 68
for 72
-----------
Five field
foreach 272
for 193
foreach 273
for 191
foreach 272
for 190
foreach 271
for 190
foreach 275
for 188
Run Code Online (Sandbox Code Playgroud)
正如我们在结果中看到的那样,"foreach"总是比"for"花费更多的时间.
因此,在迭代值类型的泛型集合时,我是否应该使用"for"而不是"foreach"?
注意:感谢提醒,我编辑了代码和结果.但仍然,foreach运行速度慢于.
Eri*_*ert 26
你的问题太复杂了.分解.
使用"foreach"迭代一系列值类型是否会创建序列的副本?
没有.
使用"foreach"迭代一系列值类型是否会创建每个值的副本?
是.
使用"for"对索引的值类型序列进行等效迭代是否会创建每个值的副本?
通常,是的.如果你知道关于集合的特殊事情,你可以做些什么来避免复制,例如它是一个数组.但是在索引集合的一般情况下,索引序列会返回序列中值的副本,而不是对包含该值的存储位置的引用.
对值类型执行任何操作都会复制该值吗?
大概.值类型按值复制.这就是为什么他们被称为价值类型.您对值不进行复制的类型进行的唯一操作是调用值类型上的方法,并使用"out"或"ref"传递值类型变量.值类型不断复制; 这就是值类型通常比引用类型慢的原因.
使用"foreach"或"for"迭代一系列引用类型复制引用吗?
是.引用类型的表达式的值是引用.无论何时使用,都会复制该引用.
那么就它们的复制行为而言,值类型和引用类型之间的区别是什么?
值类型按值复制.引用类型复制引用,但不复制引用的内容.每次使用时,16字节值类型会复制16个字节.每次使用时,16字节引用类型都会复制4(或8)字节引用.
foreach循环比for循环慢吗?
通常是.foreach循环通常做更多工作,因为它在枚举器上创建枚举器和调用方法,而不是仅仅递增整数.整数增量非常快.另外,不要忘记必须处理foreach循环中的枚举器,这也需要时间.
我应该使用for循环而不是foreach循环,因为for循环有时会快几微秒?
不,那是愚蠢的.您应该根据以客户为中心的经验数据做出明智的工程决策.foreach循环的额外负担很小.客户可能永远不会注意到.你应该做的是:
如果你遇到性能问题,将foreach循环更改为for循环将对你的问题没有任何影响.以首先看起来清晰易懂的方式编写代码.
Ada*_*son 13
你的测试不准确; 在foreach
版本中,您实际上是在调整枚举器并从列表中检索每个值(即使您没有使用它).在for
版本中,除了查看其Count
属性之外,您根本不对列表执行任何操作.实际上,与将整数变量递增相等的次数相比,您实际上是在测试遍历集合的枚举器的性能.
要创建奇偶校验,您需要声明一个临时变量并在循环的每次迭代中分配它for
.
话虽如此,你的问题的答案是肯定的.将使用每个赋值或return
语句创建值的副本.
这个伪代码细分应该解释为什么foreach
比for
在这个特定实例中使用要慢一些:
foreach
:
try
{
var en = test.GetEnumerator(); //creates a ListEnumerator
T item;
while(en.MoveNext()) // MoveNext increments the current index and returns
// true if the new index is valid, or false if it's
// beyond the end of the list. If it returns true,
// it retrieves the value at that index and holds it
// in an instance variable
{
item = en.Current; // Current retrieves the value of the current instance
// variable
}
}
finally { }
Run Code Online (Sandbox Code Playgroud)
for
:
int index = -1;
T item;
while(++index < test.Count)
{
item = test[index];
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,for
实现中的代码更少,并且foreach
在其上面有一个抽象层(枚举器)for
.我编写了for
使用while
循环来以类似的方式显示两个版本.
你说的是执行时间的微不足道的差异.使用使代码更清晰,更小的循环,并在这种情况下看起来像foreach
.
归档时间: |
|
查看次数: |
4073 次 |
最近记录: |