列挙オブジェクトのプロパティ設定が機能しないのはなぜですか?
-
11-07-2019 - |
質問
C#についてはよく知っていますが、これは私を困らせており、Googleは支援していません。
オブジェクトのIEnumerable範囲があります。最初のプロパティにプロパティを設定します。そうしますが、変更後にオブジェクトの範囲を列挙しても、変更が表示されません。
問題の良い例を次に示します。
public static void GenericCollectionModifier()
{
// 1, 2, 3, 4... 10
var range = Enumerable.Range(1, 10);
// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i});
Write(items); // Expect to output 1,2,3,4,5,6,7,8,9,10
// Make a change
items.First().MagicNumber = 42;
Write(items); // Expect to output 42,2,3,4,5,6,7,8,9,10
// Actual output: 1,2,3,4,5,6,7,8,9,10
}
public static void Write(IEnumerable<SubItem> items)
{
Console.WriteLine(string.Join(", ", items.Select(item => item.MagicNumber.ToString()).ToArray()));
}
public class SubItem
{
public string Name;
public int MagicNumber;
}
C#のどの側面が<!> quot; MagicNumber = 42 <!> quot;を止めるのか出力されることからの変化? <!> quot; stick <!> quot;への変更を取得する方法はありますか? List <!> lt; <!> gt;へのファンキーな変換を行わずにまたは配列?
ありがとう! -マイク
解決
First()を呼び出すと、次のコードの結果を列挙します。
Select(i => new SubItem() {Name = "foo", MagicNumber = i});
Selectは怠enumな列挙子であることに注意してください。つまり、Selectからアイテムを要求するときにのみ選択を行います(また、要求するたびに 実行します)。結果はどこにも保存されないため、items.First()を呼び出すと、新しいSubItem
インスタンスが取得されます。その後、項目をWriteに渡すと、以前に取得したものではなく、新しい<=>インスタンスが大量に取得されます。
選択の結果を保存して変更する場合は、次のようにする必要があります。
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i}).ToList();
他のヒント
バックグラウンドで何かが起こっていると思われます。最も可能性が高いのは、IEnumerablesを1回しか反復できないという事実によるものです。
「items」に割り当てるときにSelect()の呼び出し後に「ToList()」を追加すると機能しますか?
私が考えることができる唯一のことは、items.First()が参照ではなくSubItemのコピーをあなたに渡すので、あなたがそれを設定するとき、変更は引き継がれないことです。
IQueryableは1回しか反復できないことと関係があると仮定する必要があります。これを変更してみてください:
// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i});
to
// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i}).ToList();
さらに、別の結果があるかどうかを確認します。
列挙子を使用してコレクションを変更することはできません/すべきではありません。これが例外をスローしないことに驚いています。
.First()はメソッドであり、プロパティではありません。 Enumerableの最初の位置にあるオブジェクトの新しいインスタンスを返します。