for (var keyValue = 0; keyValue < dwhSessionDto.KeyValues.Count; keyValue++)
{...}
var count = dwhSessionDto.KeyValues.Count;
for (var keyValue = 0; keyValue < count; keyValue++)
{...}
我知道两者之间存在差异,但其中一种比另一种更快?我认为第二个更快。
答案 0 :(得分:39)
是的,第一个版本很多更慢。毕竟,我假设你正在处理这样的类型:
public class SlowCountProvider
{
public int Count
{
get
{
Thread.Sleep(1000);
return 10;
}
}
}
public class KeyValuesWithSlowCountProvider
{
public SlowCountProvider KeyValues
{
get { return new SlowCountProvider(); }
}
}
在这里,你的第一个循环需要大约10秒钟,而你的第二个循环需要大约1秒钟。
当然,您可能会认为您使用此代码的假设是不合理的 - 但我的观点是正确的答案将取决于所涉及的类型,而问题并未说明这些类型是什么。< / p>
现在,如果你实际上处理一种类型,其中访问KeyValues
和Count
便宜(很可能),我不希望有太多区别。请注意,我几乎总是喜欢尽可能使用foreach
:
foreach (var pair in dwhSessionDto.KeyValues)
{
// Use pair here
}
这样你永远不需要计数。但是,你还没有说过你在循环中想做什么。 (提示:要获得更有用的答案,provide more information。)
答案 1 :(得分:6)
它取决于计算dwhSessionDto.KeyValues.Count
的难度,如果它只是指向int
的指针,那么每个版本的速度将是相同的。但是,如果需要计算Count
值,则每次都会计算它,因此会妨碍性能。
编辑 - 继承了一些代码,以证明条件总是经过重新评估
public class Temp
{
public int Count { get; set; }
}
static void Main(string[] args)
{
var t = new Temp() {Count = 5};
for (int i = 0; i < t.Count; i++)
{
Console.WriteLine(i);
t.Count--;
}
Console.ReadLine();
}
输出为0,1,2 - 仅!
答案 2 :(得分:1)
请参阅评论,了解答案错误的原因。
如果存在差异,那就相反:事实上,第一个可能会更快。那是因为编译器识别出你正在从0迭代到数组的末尾,因此它可以忽略循环中的边界检查(即当你访问 dwhSessionDTo.KeyValues[i]
时)。
但是,我相信编译器只将此优化应用于数组,因此这里可能没有区别。
答案 3 :(得分:1)
如果不知道dwhSessionDto.KeyValues.Count
和循环体的实现,就不可能说。
假设全局变量bool foo = false;
,然后执行以下实现:
/* Loop body... */
{
if(foo) Thread.Sleep(1000);
}
/* ... */
public int Count
{
get
{
foo = !foo;
return 10;
}
}
/* ... */
现在,第一个循环的速度大约是第二个循环的两倍; D
然而,假设非愚蠢的实施,第二个确实更有可能更快。
答案 4 :(得分:0)
没有。这两个循环之间没有性能差异。使用JIT
和Code Optimization
,它没有任何区别。
答案 5 :(得分:0)
没有区别,但为什么你认为存在差异,请你发表你的发现吗?
如果您在使用反射器
的字典中看到插入项的实现private void Insert(TKey key, TValue value, bool add)
{
int freeList;
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (this.buckets == null)
{
this.Initialize(0);
}
int num = this.comparer.GetHashCode(key) & 0x7fffffff;
int index = num % this.buckets.Length;
for (int i = this.buckets[index]; i >= 0; i = this.entries[i].next)
{
if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
if (add)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
this.entries[i].value = value;
this.version++;
return;
}
}
if (this.freeCount > 0)
{
freeList = this.freeList;
this.freeList = this.entries[freeList].next;
this.freeCount--;
}
else
{
if (this.count == this.entries.Length)
{
this.Resize();
index = num % this.buckets.Length;
}
freeList = this.count;
this.count++;
}
this.entries[freeList].hashCode = num;
this.entries[freeList].next = this.buckets[index];
this.entries[freeList].key = key;
this.entries[freeList].value = value;
this.buckets[index] = freeList;
this.version++;
}
Count是此类的内部成员,每个项目都会在项目中插入
所以我相信没有任何区别。
答案 6 :(得分:0)
第二个版本有时会更快。关键是在每次迭代后重新评估条件,因此,例如, “Count”的getter实际上会对IEnumerable中的元素进行计数,或者对数据库/ etc进行interog,这会减慢速度。
所以我要说如果你不影响“for”中“Count”的值,那么第二个版本会更安全。