C # Как я могу узнать, является ли IEnumerable изменчивым? - PullRequest
9 голосов
/ 18 мая 2010

Я хочу, чтобы метод обновлял определенные записи IEnumerable.Я обнаружил, что выполнить foreach над записями и обновить значения не удалось, так как в фоновом режиме я клонировал коллекцию.Это произошло потому, что мой IEnumerable был поддержан некоторыми запросами LINQ-> SQL.

Изменяя метод для получения списка, я изменил это поведение, списки всегда изменяются, и, следовательно, метод изменяет фактические объекты в списке.,Вместо того, чтобы требовать передачи списка, есть ли изменяемый интерфейс, который я могу использовать?

    // 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; }
    }

Ответы [ 2 ]

15 голосов
/ 18 мая 2010

Вы вообще не меняете список здесь - сама коллекция может быть неизменной, и этот код все равно будет "работать". Вы изменяете данные в элементах коллекции.

Представьте себе ряд домов - они довольно неизменны (создание или разрушение дома сложно), но вы все равно можете изменить содержимое этих домов.

Итак, вам действительно нужно знать, будут ли клонированы элементы коллекции или нет ... будете ли вы получать коллекцию "новых" заданий каждый раз, когда выполняете запрос, или будет ли он использовать существующие объекты.

2 голосов
/ 18 мая 2010

Вот один гипотетический способ, которым это могло бы произойти. Допустим, у вас есть метод, который берет существующий источник данных и создает 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, в список, где они сохранятся, и, таким образом, ваш цикл UpdateYesterday и foreach будет ссылаться на те же объекты (те, что в списке, который вы создали).

Это имеет смысл? Я думаю, что это вполне может быть проблемой, с которой вы столкнулись (в этом случае ответ, действительно, заключается в создании коллекции, такой как List<Job> в памяти, из которой вы можете получить доступ к элементам для манипулирования).

В ответ на ваш вопрос о возможности определить, является ли IEnumerable изменчивым или нет, хотя ... ну, я действительно не думаю, , что возможно.

Я удалил старый ответ, так как новый, кажется, нужен ОП.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...