3

私は 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;
    }

「MagicNumber = 42」の変更が出力されない C# の側面は何ですか? List<> または配列へのファンキーな変換を行わずに、変更を「固定」する方法はありますか?

ありがとう!-マイク

4

5 に答える 5

8

First() を呼び出すと、このコードの結果が列挙されます。

Select(i => new SubItem() {Name = "foo", MagicNumber = i});

Select は遅延列挙子であることに注意してください。つまり、そこからアイテムを要求したときにのみ選択を行います (また、要求するたびに行います)。結果はどこにも保存されないため、items.First() を呼び出すと、新しいSubItemインスタンスが取得されます。その後、アイテムを Write に渡すと、以前に取得したSubItemものではなく、大量の新しいインスタンスが取得されます。

選択の結果を保存して変更したい場合は、次のようにする必要があります。

var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i}).ToList();
于 2008-11-25T14:35:44.577 に答える
0

バックグラウンドで何かが起こっているのではないかと疑っています。ほとんどの場合、IEnumerables は 1 回しか反復できないためです。

「アイテム」に割り当てるときに、Select() の呼び出しの後に「ToList()」を追加すると機能しますか?

于 2008-11-25T14:34:15.687 に答える
0

私が考えることができる唯一のことは、 items.First() が参照の代わりに SubItem のコピーをあなたに渡すことです。そのため、それを設定しても変更は引き継がれません。

IQueryable が 1 回しか反復できないことに関係があると想定する必要があります。これを変更してみてください:

// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i});

// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i}).ToList();

そして、異なる結果があるかどうかを確認します。

于 2008-11-25T14:34:36.823 に答える
0

列挙子を使用してコレクションを変更することはできません/すべきではありません。これが例外をスローしないことに驚いています。

于 2008-11-25T14:39:34.677 に答える
0

.First() はメソッドであり、プロパティではありません。Enumerable の最初の位置にあるオブジェクトの新しいインスタンスを返します。

于 2008-11-25T14:40:48.123 に答える