что с этим foreach в c #?

#c# #loops #foreach #compiler-errors

#c# #петли #foreach #ошибки компилятора

Вопрос:

(правка: небольшая доработка кода.)

Использование 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; });
 

Комментарии:

1. Если вам не нужен делегат там, вы должны использовать обычный foreach цикл, а не ForEach() метод.

Ответ №1:

Я бы рекомендовал вам просто использовать обычный foreach цикл для преобразования данных. Вы используете метод, который существует только в List<T> реализации, но не в массивах.

Использование метода for foreach на самом деле ничего вам не даст, если только по какой-то причине вы не хотели выполнять мутацию данных в цепочке методов. В этом случае вы также можете написать свой собственный метод расширения для IEnumerable<T> . Однако я бы не рекомендовал этого делать.

Наличие отдельного foreach цикла дает понять читателю, что происходит мутация данных. Это также устраняет накладные расходы на вызов делегата для каждой итерации цикла. Он также будет работать независимо от типа коллекции, если он является an 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

Как вы можете видеть, число = 1 в лямбда-выражении не имело никакого эффекта. На самом деле, если бы вы попробовали это в обычном foreach цикле, вы бы получили ошибку компилятора.

Ответ №2:

Вы используете два разных. ForEach

Массив.ForEach в byte[,,] примере (хотя вы используете его неправильно) и список.ForEach в List<...> примере.

Ответ №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);
        }
    }
}
 

Кроме того, ForEach метод в Array версии не является методом экземпляра, это метод statis. Вы называете это так:

 Array.ForEach(array, delegate);
 

Ответ №5:

необработанные массивы имеют гораздо меньше методов экземпляра, чем универсальные коллекции, поскольку они не являются шаблонными. Эти методы, такие как ForEach() or Sort() , обычно реализуются как статические методы, которые сами являются шаблонными.

В этом случае Array.Foreach(a, action) все будет сделано для массива.

Конечно, классический foreach(var b in a) метод будет работать как для списка, так и для массива, поскольку для него требуется только перечислитель.

Однако:

  1. Я не уверен, как вы будете перебирать многомерный массив.
  2. Ваше назначение (b=1) не будет работать. Потому что вы получаете значение, а не ссылку.

Ответ №6:

List имеет метод первого экземпляра. Массивы этого не делают.