как дела с этим foreach в c #? - PullRequest
       32

как дела с этим foreach в c #?

5 голосов
/ 28 октября 2011

(правка: немного кода).

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

Ответы [ 6 ]

3 голосов
/ 28 октября 2011

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

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

Наличие отдельного цикла 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

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

2 голосов
/ 28 октября 2011

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

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

1 голос
/ 28 октября 2011

Я не знаю метода 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);
1 голос
/ 28 октября 2011

Вы использовали синтаксис метода 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++)             
0 голосов
/ 28 октября 2011

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

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

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

Тем не менее:

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

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

...