С# с использованием предиката действия Array.ForEach с массивом типа значения или строки

StackOverflow https://stackoverflow.com/questions/561170

  •  05-09-2019
  •  | 
  •  

Вопрос

Правильно ли я считаю, что следующий фрагмент не работает (элементы массива не изменяются) потому что массив имеет целое число, которое является типом значения.

class Program
{
    public static void Main()
    {
        int[] ints = new int[] { 1,2 };

        Array.ForEach(ints, new Action<int>(AddTen));

        // ints is not modified
    }
    static void AddTen(int i)
    {
        i+=10;
    }
}

То же самое было бы применимо, если бы в примере использовался массив строк, предположительно потому, что строка неизменяема.

У меня вопрос:-

Есть ли способ обойти это?Я не могу изменить подпись метода обратного вызова, например, добавив ключевое слово ref, и я не хочу заключать тип значения в класс, который будет работать...

(Конечно, для этого я мог бы просто написать старомодный цикл foreach!)

Это было полезно?

Решение

Вы просто меняете локальную переменную, а не элемент в списке.Для этого вам нужно ConvertAll, который создает новый список/массив:

    int[] ints = new int[] { 1,2 };

    int[] newArr = Array.ConvertAll<int,int>(ints, AddTen);

с:

static int AddTen(int i)
{
    return i+10;
}

Это также можно записать с помощью анонимного метода:

int[] newArr = Array.ConvertAll<int,int>(ints,
    delegate (int i) { return i+ 10;});

Или в C# 3.0 как лямбда:

int[] newArr = Array.ConvertAll(ints, i=>i+10);

Кроме этого...а for петля:

for(int i = 0 ; i < arr.Length ; i++) {
    arr[i] = AddTen(arr[i]); // or more directly...
}

Но так или иначе вам придется получить значение вне вашего метода.Если вы не измените подпись, вы не сможете.

Другие советы

Метод Array.ForEach() не позволит вам практически изменять его члены.Вы можете изменить его, используя LINQ, например этот

ints = ints.Select(x => x +10 ).ToArray();

foreach — единственный способ, типы значений в массивах и списках всегда копируются, и поэтому их изменение не сработает, если вы не сохраните измененное значение обратно.Метод AddTen этого не делает, он изменяет свою собственную копию.

Во-первых, вносить изменения в коллекцию, которую вы собираете, обычно опасно. foreachвсе закончилось.Большинство коллекций поддерживают внутренний «тег версии» для отслеживания изменений, поэтому перечислитель выдает исключение при попытке перебрать измененную коллекцию.

Что касается вашего вопроса, вы не сможете сделать это с типами значений и Array.ForEach.Использовать foreach или Convert делать то, что ты хочешь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top