9

IEnumerable の特定のエントリを更新するメソッドが必要です。バックグラウンドでコレクションのクローンを作成していたため、エントリに対して foreach を実行して値を更新できないことがわかりました。これは、私の IEnumerable がいくつかの LINQ->SQL クエリによって支えられていたためです。

リストを取るメソッドを変更することで、この動作を変更しました。リストは常に可変であるため、メソッドはリスト内の実際のオブジェクトを変更します。List が渡されることを要求するのではなく、使用できる Mutable インターフェイスはありますか?

    // Will not behave as consistently for all IEnumerables
    public void UpdateYesterday (IEnumerable<Job> jobs) {
          foreach (var job in jobs.Where(x => x.date == Yesterday)) {
             job.done = true;
          }
    }

    ...

    public class Job {  
         ...           
         public DateTime Date { get; set; }
    }
4

2 に答える 2

15

ここではリストをまったく変更していません。コレクション自体は不変である可能性があり、このコードは引き続き「機能」します。コレクション内のアイテム内のデータを変更しています。

家の列を想像してみてください-それはかなり不変です(家を作成または破壊するのは難しいです)が、それらの家の内容を変更することはできます。

したがって、本当に知っておく必要があるのは、コレクションの要素が複製されるかどうか、クエリを実行するたびに「新しい」ジョブのコレクションを取得するかどうか、またはそれを使用するかどうかです。既存のオブジェクト。

于 2010-05-18T09:45:59.997 に答える
2

これが起こる可能性のある仮説的な方法の 1 つを次に示します。既存のデータ ソースを取得し、そのソースからオブジェクトを作成するメソッドがあるとします。 Job

このようなもの:

public IEnumerable<Job> GetJobs() {
    var rows = GetRowsFromDatabaseTable();

    foreach (var row in rows)
        yield return new Job(row.Name, row.Date, row.Etc);
}

次に、これを行うコードがある場合:

var jobs = GetJobs();

UpdateYesterday(jobs);

foreach (var job in jobs)
    Console.WriteLine(job);

を使用して印刷したジョブには、Console.WriteLineで実行した更新が反映されていないことがわかりますUpdateYesterday。これは、UpdateYesterdayによって作成された新しいオブジェクトを列挙したGetJobs後、によって (再び)作成された新しいオブジェクトの新しいセットをforeachループで列挙したためです。GetJobs

一方、単に最初の行を次のように変更した場合:

var jobs = GetJobs().ToList();

次に、によって作成されたすべての新しいオブジェクトGetJobsをリストに入れ、そこで永続化するため、UpdateYesterdayandforeachループは同じオブジェクト (作成したリスト内のもの) を参照します。

それは理にかなっていますか?私はこれがあなたが遭遇している問題である可能性が非常に高いと思います (その場合、答えは実際には、List<Job>メンバーにアクセスして操作できるメモリ内などのコレクションを構築することです)。

ただし、 an が変更可能かどうかを判断できるかどうかについての質問への回答では...まあ、それIEnumerableが可能だとは本当に思いません。

新しい回答はOPが必要としていたように見えるため、古い回答を削除しました。

于 2010-05-18T12:48:45.460 に答える