C# How can I tell if an IEnumerable is Mutable?
I want a method to update certain entries of an IEnumerable. I found that doing a foreach over the entries and updating the values failed as in the background I was cloning the collection. This was because my IEnumerable was backed by some LINQ->SQL queries.
By changing the method to take a List I have changed this behavior, Lists are always mutable and hence the method changes the a开发者_JS百科ctual objects in the list. Rather than demand a List is passed is there a Mutable interface I can use?
// 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; }
}
You're not changing the list at all here - the collection itself could be immutable and this code would still "work". You're changing the data within the items in the collection.
Imagine a row of houses - that's pretty immutable (creating or destroying a house is tricky) but you can still change the contents of those houses.
So, what you really need to know is whether the elements of the collection are going to be cloned or not... whether you'll get a collection of "new" jobs each time you perform the query, or whether it'll use the existing objects.
Here's one hypothetical way this might happen. Say you have a method that takes an existing data source and creates Job
objects from that source.
Something like this:
public IEnumerable<Job> GetJobs() {
var rows = GetRowsFromDatabaseTable();
foreach (var row in rows)
yield return new Job(row.Name, row.Date, row.Etc);
}
Then if you had code that did this:
var jobs = GetJobs();
UpdateYesterday(jobs);
foreach (var job in jobs)
Console.WriteLine(job);
You would find that the jobs you printed using Console.WriteLine
did not reflect the updates you performed in UpdateYesterday
. This is because UpdateYesterday
would have enumerated over the new objects created by GetJobs
, and then your foreach
loop would have enumerated over a new set of new objects created (again) by GetJobs
.
On the other hand, if you simply changed that first line to this:
var jobs = GetJobs().ToList();
Then you would have put all those new objects created by GetJobs
into a list, where they would persist, and thus your UpdateYesterday
and foreach
loop would be referring to the same objects (the ones in the list you created).
Does that make sense? I think this could very well be the problem you're encountering (in which case, the answer is indeed to construct a collection such as a List<Job>
in memory from which you can access members to manipulate).
In answer to your question about being able to tell if an IEnumerable
is mutable or not, though... well, I really don't think that is possible.
I've removed the old answer, as the new one seems to be what the OP needed.
精彩评论