【问题标题】:whats up with this foreach in c#?c# 中的这个 foreach 是怎么回事?
【发布时间】:2011-12-17 09:28:55
【问题描述】:

(编辑:稍微整理一下代码。)

像这样使用 foreach 效果很好。

var a = new List<Vector2>();

a.ForEach(delegate(Vector2 b) {
    b.Normalize(); });

然而,以下导致“方法 'ForEach' 没有重载需要 1 个参数”。

byte[,,] a = new byte[2, 10, 10];

a.ForEach(delegate(byte b) {
    b = 1; });

【问题讨论】:

  • 如果你不需要代理,你应该使用普通的foreach循环,而不是ForEach()方法。

标签: c# loops foreach compiler-errors


【解决方案1】:

我建议您只使用普通的foreach 循环来转换数据。您使用的方法仅存在于 List&lt;T&gt; 实现中,但不存在于数组中。

使用foreach 的方法确实没有任何好处,除非出于某种原因您想在方法链中进行数据突变。在这种情况下,您不妨为IEnumerable&lt;T&gt; 编写自己的扩展方法。不过,我建议不要这样做。

有一个单独的foreach 循环可以让读者清楚地知道正在发生数据突变。它还消除了为循环的每次迭代调用委托的开销。无论集合类型如何,只要它是IEnumerable,它也可以工作(不完全正确,您可以编写自己的枚举器和枚举器,但这是一个不同的问题)。

如果您只想进行数据转换(即投影等),请使用 LINQ。

还请记住,使用数组时,您将获得byte 的副本,而不是引用。您将只修改 byte 而不是原来的。这是一个输出示例:

int[] numbers = new int[] { 1, 2, 3, 4, 5 };

Array.ForEach(numbers, number => number += 1);

foreach(int number in numbers)
{
    Console.WriteLine(number);
}

产生输出:

1 2 3 4 5

如您所见,lambda 中的数字 += 1 无效。事实上,如果你在一个普通的foreach 循环中尝试这个,你会得到一个编译器错误。

【讨论】:

    【解决方案2】:

    您正在使用两个不同的ForEach'es。

    byte[,,] 示例中的Array.ForEach(尽管您使用不正确)和List&lt;...&gt; 示例中的List.ForEach

    【讨论】:

      【解决方案3】:

      您已经为数组使用了List.ForEach() 方法的语法,但是Array.ForEach() 的语法是:

      public static void ForEach<T>(
          T[] array,
          Action<T> action
      )
      

      一个重要的点是数组应该是一维的,以便在Array.ForEach() 中使用它。考虑到这一点,我建议使用简单的for 循环

      // first dimension
      for (int index = 0; index < bytesArray.GetLength(0); index++)             
      
      // second dimension
      for (int index = 0; index < bytesArray.GetLength(1); index++)             
      
      // third dimension
      for (int index = 0; index < bytesArray.GetLength(2); index++)             
      

      【讨论】:

        【解决方案4】:

        我不知道采用多维数组的 ForEach 方法。 如果你想要一个,我认为你必须自己创建它。

        这是怎么做的:

            private static void ForEach<T>(T[, ,] a, Action<T> action)
            {
                foreach (var item in a)
                {
                    action(item);
                }
            }
        

        示例程序,使用新的 ForEach 方法:

        static class Program
        {
            static void Main()
            {
                byte[, ,] a = new byte[2, 10, 10];
        
                ForEach(a, delegate(byte b)
                {
                    Console.WriteLine(b);
                });
            }
            private static void ForEach<T>(T[, ,] a, Action<T> action)
            {
                foreach (var item in a)
                {
                    action(item);
                }
            }
        }
        

        另外,Array 版本中的ForEach 方法,不是实例方法,而是统计方法。你这样称呼它:

        Array.ForEach(array, delegate);
        

        【讨论】:

          【解决方案5】:

          原始数组的实例方法比泛型集合少得多,因为它们没有模板化。这些方法,例如ForEach()Sort(),通常作为静态方法实现,它们本身是模板化的。

          在这种情况下,Array.Foreach(a, action) 将为数组解决问题。

          当然,经典的 foreach(var b in a) 对 List 和 Array 都适用,因为它只需要一个枚举器。

          但是:

          1. 我不确定您将如何遍历多维数组。
          2. 您的分配(b=1) 将不起作用。因为您收到的是价值,而不是参考。

          【讨论】:

            【解决方案6】:

            List 有第一个实例方法。数组没有。

            【讨论】:

              猜你喜欢
              • 2013-07-28
              • 1970-01-01
              • 2011-06-28
              • 2020-04-03
              • 2018-06-20
              • 2011-08-25
              • 1970-01-01
              • 1970-01-01
              • 2022-07-18
              相关资源
              最近更新 更多