Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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中vs foreach差异的循环#_C#_.net_Performance_Dictionary_Foreach - Fatal编程技术网

C# 迭代字典c中vs foreach差异的循环#

C# 迭代字典c中vs foreach差异的循环#,c#,.net,performance,dictionary,foreach,C#,.net,Performance,Dictionary,Foreach,我有一个followforeach循环来完成这项工作。我很想知道下面的例子-对于性能问题,使用for循环而不是foreach循环是否更好 因为我读到for循环比foreach循环快,所以我也有点困惑 foreach (KeyValuePair<string, StringValues> v in values) { string key = v.Key; StringValues val = v.Value; if (val.Count &

我有一个follow
foreach
循环来完成这项工作。我很想知道下面的例子-对于性能问题,使用
for
循环而不是
foreach
循环是否更好

因为我读到
for
循环比
foreach
循环快,所以我也有点困惑

  foreach (KeyValuePair<string, StringValues> v in values)
  {
      string key = v.Key;
      StringValues val = v.Value;
      if (val.Count > 0)
      {
          if (!string.IsNullOrWhiteSpace(val[0]))
          {
              switch (key)
              {
                  case ABC:
                      One = val[0];
                      break;
                  case PQR:
                      Two = val[0];
                      break;
                  //.. bunch of other case block here with similar stuff
              }
          }
      }
  }
foreach(值中的KeyValuePair v)
{
字符串键=v.键;
StringValues val=v.值;
如果(值计数>0)
{
如果(!string.IsNullOrWhiteSpace(val[0]))
{
开关(钥匙)
{
案例ABC:
1=val[0];
打破
案例PQR:
二=val[0];
打破
//…这里还有一堆类似的箱子
}
}
}
}

只有在非常极端的情况下才有意义。在
foreach
中,性能下降是您必须写入另一个变量,而在
for
中,您不需要这样做。 foreach基本上是这样的:

for(inti=0,i
由于词典没有定义的顺序,在
IDictionary
界面中缺少任何类型的索引器,这可能会使不使用
foreach
/
GetEnumerator()
的情况下很难进行迭代。鉴于

Dictionary Dictionary=Enumerable.Range(0,10).ToDictionary(i=>i,i=>-i);
…因为您知道键包含一个连续的整数范围,所以可以使用
for
循环遍历所有可能的键值

//这利用了我们知道字典中存在0..9中的键这一事实
for(int key=0;key
然而,如果你不能做出这样的假设,它就会变得更加棘手。您可以迭代以获取每个元素的键…但该集合也不允许索引,因此您回到了从
foreach
for
困境开始的位置。但是,如果您坚持使用
for
,一种方法是对数组执行
键,然后迭代该数组

//将Keys属性复制到数组以允许索引
int[]keys=newint[dictionary.Count];
dictionary.key.CopyTo(key,0);
//这对字典中键的分布没有任何假设
for(int index=0;index
当然,
CopyTo()
将在您自己有机会枚举
键之前枚举一次完整的时间,因此这只会影响性能

如果您使用的是一组预先已知的固定键,或者您不介意每次字典的键更改时都必须维护一个单独的键集合,那么更好的方法是将键缓存在一个可以索引的结构中

int[]keyCache=Enumerable.Range(0,10).ToArray();
// ...
//这将检索与字典分开存储的已知键
for(int index=0;index
可能会很有诱惑力地使用;毕竟,它很容易使用

for(int index=0;index
但是,这对性能非常不利
ElementAt()
仅当输入集合实现了
IList
时才能执行,而
Dictionary
既不继承,也不继承。否则,对于尝试检索的每个索引,都必须从头开始。考虑枚举上面定义的整个10元字典…

| Index requested | Elements enumerated | Total elements enumerated | |:---------------:|:----------------------------:|:-------------------------:| | 0 | 0 | 1 | | 1 | 0, 1 | 3 | | 2 | 0, 1, 2 | 6 | | 3 | 0, 1, 2, 3 | 10 | | 4 | 0, 1, 2, 3, 4 | 15 | | 5 | 0, 1, 2, 3, 4, 5 | 21 | | 6 | 0, 1, 2, 3, 4, 5, 6 | 28 | | 7 | 0, 1, 2, 3, 4, 5, 6, 7 | 36 | | 8 | 0, 1, 2, 3, 4, 5, 6, 7, 8 | 45 | | 9 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 | 55 | …从这个我用

使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
使用BenchmarkDotNet.Attributes;
使用BenchmarkDotNet.Jobs;
名称空间SO61507883
{
[SimpleJob(RuntimeMoniker.Net48)]
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
公共课基准
{
公共静态IReadOnlyList字典
{
得到;
}=Array.AsReadOnly(新的int[]{10,1_000});
[ParamsSource(名称(字典化))]
公共整数大小
{
获得;设置;
}
公共词典源
{
获得;设置;
}
//仅由*_CachedKeys()基准方法使用
公共int[]密钥缓存
{
获得;设置;
}
[全局设置()]
公共作废设置()
{
Source=可枚举范围(0,大小)
.ToDictionary(i=>i,i=>-i);
KeyCache=newint[Size];
Source.Keys.CopyTo(KeyCache,0);
}
[基准测试()]
public(int-keySum,int-valueSum)GetEnumerator()
{
int-keySum=0;
int valueSum=0;
使用(Dictionary.Enumerator Enumerator=Source.GetEnumerator())
while(枚举数.MoveNext())
{
KeyValuePair=枚举数。当前值;
keySum+=pair.Key;
valueSum+=成对值;
}
返回值(keySum、valueSum);
}
[基准(基线=真实)]
public(int-keySum,int-valueSum)ForEach()
{
int-keySum=0;
int valueSum=0;
foreach(源中的KeyValuePair对)
{
keySum+=pair.Key;
valueSum+=成对值;
}
返回(键
// * Summary *

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.657 (1909/November2018Update/19H2)
Intel Core i7 CPU 860 2.80GHz (Nehalem), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.201
  [Host]        : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
  .NET 4.8      : .NET Framework 4.8 (4.8.4121.0), X64 RyuJIT
  .NET Core 3.1 : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT


|                            Method |           Job |       Runtime |   Size |                Mean |             Error |            StdDev |     Ratio | RatioSD |
|---------------------------------- |-------------- |-------------- |------- |--------------------:|------------------:|------------------:|----------:|--------:|
|                     GetEnumerator |      .NET 4.8 |      .NET 4.8 |     10 |            118.4 ns |           1.71 ns |           1.76 ns |      1.02 |    0.02 |
|                           ForEach |      .NET 4.8 |      .NET 4.8 |     10 |            116.4 ns |           1.44 ns |           1.28 ns |      1.00 |    0.00 |
|       For_Indexer_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |     10 |            147.6 ns |           2.96 ns |           3.17 ns |      1.26 |    0.02 |
|     While_Indexer_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |     10 |            149.2 ns |           1.72 ns |           1.61 ns |      1.28 |    0.02 |
|   For_TryGetValue_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |     10 |            154.5 ns |           1.16 ns |           0.97 ns |      1.33 |    0.01 |
| While_TryGetValue_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |     10 |            160.8 ns |           1.93 ns |           1.71 ns |      1.38 |    0.01 |
|            For_Indexer_CopyToKeys |      .NET 4.8 |      .NET 4.8 |     10 |            177.5 ns |           1.37 ns |           1.14 ns |      1.53 |    0.02 |
|          While_Indexer_CopyToKeys |      .NET 4.8 |      .NET 4.8 |     10 |            185.6 ns |           3.69 ns |           4.80 ns |      1.59 |    0.05 |
|            For_Indexer_CachedKeys |      .NET 4.8 |      .NET 4.8 |     10 |            154.5 ns |           2.83 ns |           2.64 ns |      1.33 |    0.03 |
|          While_Indexer_CachedKeys |      .NET 4.8 |      .NET 4.8 |     10 |            155.3 ns |           2.35 ns |           2.08 ns |      1.33 |    0.02 |
|                     For_ElementAt |      .NET 4.8 |      .NET 4.8 |     10 |          1,009.2 ns |           8.61 ns |           7.19 ns |      8.67 |    0.12 |
|                   While_ElementAt |      .NET 4.8 |      .NET 4.8 |     10 |          1,140.9 ns |          14.36 ns |          13.43 ns |      9.81 |    0.16 |
|                                   |               |               |        |                     |                   |                   |           |         |
|                     GetEnumerator | .NET Core 3.1 | .NET Core 3.1 |     10 |            118.6 ns |           2.39 ns |           3.19 ns |      0.98 |    0.03 |
|                           ForEach | .NET Core 3.1 | .NET Core 3.1 |     10 |            120.3 ns |           1.28 ns |           1.14 ns |      1.00 |    0.00 |
|       For_Indexer_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            126.1 ns |           0.67 ns |           0.56 ns |      1.05 |    0.01 |
|     While_Indexer_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            135.5 ns |           2.28 ns |           2.02 ns |      1.13 |    0.02 |
|   For_TryGetValue_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            131.0 ns |           2.41 ns |           2.25 ns |      1.09 |    0.02 |
| While_TryGetValue_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            133.9 ns |           1.42 ns |           1.19 ns |      1.11 |    0.01 |
|            For_Indexer_CopyToKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            162.4 ns |           2.32 ns |           2.06 ns |      1.35 |    0.02 |
|          While_Indexer_CopyToKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            166.3 ns |           1.29 ns |           1.21 ns |      1.38 |    0.02 |
|            For_Indexer_CachedKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            136.0 ns |           1.27 ns |           1.19 ns |      1.13 |    0.02 |
|          While_Indexer_CachedKeys | .NET Core 3.1 | .NET Core 3.1 |     10 |            142.3 ns |           2.84 ns |           4.59 ns |      1.14 |    0.02 |
|                     For_ElementAt | .NET Core 3.1 | .NET Core 3.1 |     10 |            952.4 ns |          10.08 ns |           8.94 ns |      7.92 |    0.13 |
|                   While_ElementAt | .NET Core 3.1 | .NET Core 3.1 |     10 |            953.8 ns |           8.86 ns |           7.40 ns |      7.93 |    0.12 |
|                                   |               |               |        |                     |                   |                   |           |         |
|                     GetEnumerator |      .NET 4.8 |      .NET 4.8 |   1000 |          9,344.9 ns |          80.50 ns |          75.30 ns |      1.00 |    0.01 |
|                           ForEach |      .NET 4.8 |      .NET 4.8 |   1000 |          9,360.2 ns |          82.04 ns |          64.05 ns |      1.00 |    0.00 |
|       For_Indexer_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         15,122.4 ns |          81.71 ns |          68.23 ns |      1.62 |    0.01 |
|     While_Indexer_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         15,106.4 ns |          85.68 ns |          75.96 ns |      1.61 |    0.02 |
|   For_TryGetValue_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         16,160.3 ns |         270.09 ns |         252.64 ns |      1.73 |    0.03 |
| While_TryGetValue_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         16,452.4 ns |         146.51 ns |         129.88 ns |      1.76 |    0.02 |
|            For_Indexer_CopyToKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         17,407.1 ns |         251.38 ns |         222.84 ns |      1.86 |    0.03 |
|          While_Indexer_CopyToKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         17,034.0 ns |         295.71 ns |         404.77 ns |      1.85 |    0.05 |
|            For_Indexer_CachedKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         16,277.5 ns |          69.91 ns |          58.38 ns |      1.74 |    0.02 |
|          While_Indexer_CachedKeys |      .NET 4.8 |      .NET 4.8 |   1000 |         15,131.9 ns |          55.97 ns |          46.74 ns |      1.62 |    0.01 |
|                     For_ElementAt |      .NET 4.8 |      .NET 4.8 |   1000 |      4,859,257.3 ns |      18,862.72 ns |      15,751.22 ns |    519.24 |    4.36 |
|                   While_ElementAt |      .NET 4.8 |      .NET 4.8 |   1000 |      3,837,001.5 ns |       7,396.43 ns |       6,556.74 ns |    409.85 |    3.11 |
|                                   |               |               |        |                     |                   |                   |           |         |
|                     GetEnumerator | .NET Core 3.1 | .NET Core 3.1 |   1000 |          9,029.9 ns |          21.69 ns |          18.12 ns |      1.00 |    0.00 |
|                           ForEach | .NET Core 3.1 | .NET Core 3.1 |   1000 |          9,022.4 ns |          13.08 ns |          10.92 ns |      1.00 |    0.00 |
|       For_Indexer_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         11,396.9 ns |          18.42 ns |          15.38 ns |      1.26 |    0.00 |
|     While_Indexer_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         12,504.6 ns |          13.82 ns |          10.79 ns |      1.39 |    0.00 |
|   For_TryGetValue_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         12,244.1 ns |          73.90 ns |          69.13 ns |      1.36 |    0.01 |
| While_TryGetValue_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         12,437.4 ns |          22.48 ns |          18.77 ns |      1.38 |    0.00 |
|            For_Indexer_CopyToKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         13,717.9 ns |          36.98 ns |          30.88 ns |      1.52 |    0.00 |
|          While_Indexer_CopyToKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         14,099.6 ns |          20.44 ns |          18.12 ns |      1.56 |    0.00 |
|            For_Indexer_CachedKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         12,640.4 ns |          23.31 ns |          19.47 ns |      1.40 |    0.00 |
|          While_Indexer_CachedKeys | .NET Core 3.1 | .NET Core 3.1 |   1000 |         12,610.5 ns |          20.97 ns |          17.51 ns |      1.40 |    0.00 |
|                     For_ElementAt | .NET Core 3.1 | .NET Core 3.1 |   1000 |      3,402,799.3 ns |      15,880.59 ns |      14,077.73 ns |    377.13 |    1.73 |
|                   While_ElementAt | .NET Core 3.1 | .NET Core 3.1 |   1000 |      3,399,305.2 ns |       5,822.01 ns |       5,161.06 ns |    376.76 |    0.74 |
|                                   |               |               |        |                     |                   |                   |           |         |
|                     GetEnumerator |      .NET 4.8 |      .NET 4.8 | 100000 |        885,621.4 ns |       1,617.29 ns |       1,350.51 ns |      1.00 |    0.00 |
|                           ForEach |      .NET 4.8 |      .NET 4.8 | 100000 |        884,591.8 ns |       1,781.29 ns |       1,390.72 ns |      1.00 |    0.00 |
|       For_Indexer_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,424,062.0 ns |       2,791.28 ns |       2,474.39 ns |      1.61 |    0.00 |
|     While_Indexer_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,435,667.1 ns |       3,696.89 ns |       3,277.19 ns |      1.62 |    0.00 |
|   For_TryGetValue_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,502,486.1 ns |       3,750.98 ns |       3,325.15 ns |      1.70 |    0.00 |
| While_TryGetValue_ConsecutiveKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,558,335.7 ns |       4,619.63 ns |       3,857.60 ns |      1.76 |    0.00 |
|            For_Indexer_CopyToKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,685,000.7 ns |       4,676.88 ns |       3,651.40 ns |      1.90 |    0.01 |
|          While_Indexer_CopyToKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,722,418.0 ns |       3,431.67 ns |       3,042.08 ns |      1.95 |    0.01 |
|            For_Indexer_CachedKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,499,782.0 ns |       2,951.84 ns |       2,616.73 ns |      1.70 |    0.00 |
|          While_Indexer_CachedKeys |      .NET 4.8 |      .NET 4.8 | 100000 |      1,583,570.2 ns |       3,880.57 ns |       3,440.03 ns |      1.79 |    0.00 |
|                     For_ElementAt |      .NET 4.8 |      .NET 4.8 | 100000 | 37,917,621,633.3 ns |  47,744,618.60 ns |  44,660,345.86 ns | 42,868.63 |   93.80 |
|                   While_ElementAt |      .NET 4.8 |      .NET 4.8 | 100000 | 38,343,003,642.9 ns | 262,502,616.47 ns | 232,701,732.10 ns | 43,315.66 |  229.53 |
|                                   |               |               |        |                     |                   |                   |           |         |
|                     GetEnumerator | .NET Core 3.1 | .NET Core 3.1 | 100000 |        900,980.9 ns |       2,477.29 ns |       2,068.65 ns |      1.00 |    0.00 |
|                           ForEach | .NET Core 3.1 | .NET Core 3.1 | 100000 |        899,775.7 ns |       1,040.30 ns |         868.70 ns |      1.00 |    0.00 |
|       For_Indexer_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,177,153.8 ns |       1,689.80 ns |       1,411.06 ns |      1.31 |    0.00 |
|     While_Indexer_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,255,795.4 ns |       2,562.23 ns |       2,139.58 ns |      1.40 |    0.00 |
|   For_TryGetValue_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,226,163.3 ns |       2,317.36 ns |       1,809.25 ns |      1.36 |    0.00 |
| While_TryGetValue_ConsecutiveKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,245,130.0 ns |       4,146.38 ns |       3,237.22 ns |      1.38 |    0.00 |
|            For_Indexer_CopyToKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,430,340.4 ns |       7,834.82 ns |       6,945.37 ns |      1.59 |    0.01 |
|          While_Indexer_CopyToKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,472,807.7 ns |       5,363.80 ns |       4,754.87 ns |      1.64 |    0.01 |
|            For_Indexer_CachedKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,289,902.4 ns |       2,739.78 ns |       2,139.04 ns |      1.43 |    0.00 |
|          While_Indexer_CachedKeys | .NET Core 3.1 | .NET Core 3.1 | 100000 |      1,276,484.8 ns |       4,652.23 ns |       3,884.82 ns |      1.42 |    0.00 |
|                     For_ElementAt | .NET Core 3.1 | .NET Core 3.1 | 100000 | 33,717,209,257.1 ns | 200,565,125.50 ns | 177,795,759.65 ns | 37,460.45 |  216.07 |
|                   While_ElementAt | .NET Core 3.1 | .NET Core 3.1 | 100000 | 34,064,932,086.7 ns | 225,399,893.36 ns | 210,839,200.10 ns | 37,841.10 |  204.02 |