3

配列は値型である整数であるため、次のスニペットは機能しない (配列項目は変更されない) と考えるのは正しいですか。

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 ループを記述してこれを行うこともできます!)

4

4 に答える 4

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...
}

しかし、何らかの方法で、メソッドから値を取得する必要があります。署名を変更しない限り、できません。

于 2009-02-18T14:10:10.183 に答える
4

Array.ForEach() メソッドでは、そのメンバーを実際に変更することはできません。このようなLINQを使用して変更できます

ints = ints.Select(x => x +10 ).ToArray();
于 2009-02-18T14:10:24.440 に答える
0

foreach が唯一の方法です。配列とリストの値の型は常にコピーされるため、変更した値を元に戻さない限り、それらを変更しても機能しません。AddTen メソッドはそれを行っていません。独自のコピーを変更します。

于 2009-02-18T14:11:31.083 に答える
0

まず第一に、現在処理中のコレクションを変更することは一般的に危険ですforeach。ほとんどのコレクションは、変更を追跡するために内部の「バージョン タグ」を保持しているため、変更されたコレクションを反復しようとすると、列挙子は例外をスローします。

あなたの質問に関しては、値の型とでそれを行う方法はありませんArray.ForEachforeachまたはを使用Convertして、必要なことを行います。

于 2009-02-18T14:13:14.450 に答える