2009-02-18 5 views
3

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

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, чтобы сделать это!)

ответ

9

Вы просто меняете локальную переменную - не элемент в списке. Чтобы сделать это, вы хотите 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... 
} 

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

4

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

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

Фактически, Array.ConvertAll будет делать в этом случае (и более эффективен по мере того, как длина вычисляется правильно), но этого было бы достаточно. –

+0

@Marc, узнайте что-то новое каждый день. Раньше этого не видел. Благодаря! – JaredPar

0

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

0

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^