C#, Как я могу сказать, изменяем ли IEnumerable?

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

Путем изменения метода для взятия Списка я изменил это поведение, Списки всегда изменяемы, и следовательно метод изменяет фактические объекты в списке. Вместо того, чтобы потребовать Список передается, там интерфейс 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; }
    }
9
задан Logan 18 May 2010 в 12:19
поделиться

2 ответа

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

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

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

15
ответ дан 4 December 2019 в 12:17
поделиться

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

С другой стороны, если вы просто измените эту первую строку на эту:

var jobs = GetJobs().ToList();

Затем , вы поместите все эти новые объекты, созданные с помощью GetJobs , в список, где они будут сохраняться. , и, следовательно, ваш цикл UpdateYesterday и foreach будет ссылаться на одни и те же объекты (те, что в созданном вами списке).

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

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

Я удалил старый ответ, так как новый, похоже, то, что нужно OP.

2
ответ дан 4 December 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: