2017-03-18 9 views
0

int型のリスト内のすべての数値を四角形にしようとしています。しかし、コードを実行すると、リストはまったく変更されないように見えます。linq文で値を再割り当てできません

public static List<int> SquareList(List<int> root) 
{ 
    root.ForEach(x => x = x*x); 
    return root; 
} 

x_unitのテストクラス。

[Fact] 
public void testSqures() 
{ 
    var input = new List<int> { 1, 2, 3 }; 
    var expected = new List<int> { 1, 4, 9 }; 
    var result = Square.SquareList(input); 

    Assert.Equal(expected,result); 
} 

質問foreachオペレータは、基礎となるオブジェクトを変更しないのですか?

新しいリストを作成する必要はありますか?またはその場所でリストを変換する方法がありますか?

return root.Select(x => x*x).ToList(); 

これに

+1

の、そのようなことを行うために定期的にforループを使用する必要があります: 'アクション'デリゲートの本体で基になるコレクションを変更することですサポートされていないため、未定義の動作が発生します。 – Vikhram

+0

あなたは値型で作業しており、値型は 'Action'デリゲートでは更新できません。間違いなく新しいリストを作成する必要があります。 – NoviceProgrammer

答えて

1

変更それはそれは、新しいリストを作成し、好ましいであろう、それを返し、既存のリストを変更しません。実際に元のリストを更新したい場合は、refに渡すために署名を変更して、ポインタを新しいリストに更新します。

public static List<int> SquareList(ref List<int> root) 
{ 
    root = root.Select(x => x*x).ToList(); 
    return root; 
} 

またはループのため

public static List<int> SquareList(List<int> root) 
{ 
    for(int i = 0; i < root.Count; i++) 
     root[i] = root[i]*root[i]; 
    return root; 
} 

ForEachでそれを使用し、リストを反復ん。また、あなたがintを含ん参照型(クラス)を持っていた場合は、その型の内部の値を変更することができますリストに含まれているポインタを再割り当てすることはできません。

0

Useコレクションの新しい表現を取得する場合は、ForEachの代わりにSelectを使用します。新しいオブジェクトを変更する代わりにそれを返すことは、関数型プログラミングのパラダイムです。そして、LINQはこのパラダイムを使うのに役立ちます。 MSDNから

0

:アクションデリゲートの本体で基になるコレクションを変更

がサポートされており、未定義の動作の原因とされていません。

あなただけのMSDNから、代わりにLINQまたは類似の機能声明

public static List<int> SquareList(List<int> root) 
{ 
    for (int i = 0, n = root.Count; i < n; ++i) 
     root[i] = root[i] * root[i]; 
    return root; 
} 
+0

あなたが引用した文書は、質問とは関係ありません。この警告は、コレクションの構造の変更、すなわち単純な値の置換ではなく要素の除去または挿入/追加を指す。 –

+0

@PeterDunihoあなたのポイントを証明するために、正式な文書やValueTypeのコード例がありますか? '基礎となるコレクションを変更する 'という用語と、'基礎となるコレクションが参照する値を変更する'という用語の間で混乱していると思います。 – Vikhram

+0

コレクションを変更しようとすると、_ InvalidOperationExceptionがスローされ、_コレクションが変更されました;列挙操作が実行されない可能性があります。 "これは、実際にコレクションの一部ではない値型を変更しようとする場合とはまったく異なる問題です。コード例: 'List values = new List {0、1、2}; ForEach(i => values [i] = i + 1); '、例外をスローします。'ForEach()'はリストを変更するのに使用すべきではないが、OPのコードと無関係なので、ドキュメントの特定のセクションを引用するのは間違っているのは間違いである。 –

関連する問題