Cant update IEnumerable iterator variable [duplicate] - c#

This question already has answers here:
Why can't I change elements from a linq IEnumerable in a for loop?
(3 answers)
Closed 7 years ago.
I'm stuck with next behaviour:
var contracts = result.Select(this.Map);
foreach (var contract in contracts) {
contract.Id = 1;
}
return contracts;
After loop contract.id were not updated and still have initial value.
var contracts = result.Select(this.Map).ToList(); solved my problem, but i can't figure out why couldn't I update properties of iterating variable?

You need to remember that the results of a LINQ query is an object representing the query, not the results of that query. contracts is an object that, when iterated, will perform a mapping of each object in the underlying collection to a new object. Each time it is iterated, it performs the mapping again.
In your case you're iterating the source collection, performing the mapping, editing those objects, throwing those objects on the floor, iterating the collection again, performing the mapping again, and then looking at those objects, so of course the edits you made aren't seen.
When you call ToList you're now no longer storing a query, but rather the results of that query, and edits to the items in that collection are observed, because you're looking at the same items in subsequent iterations.

Related

Why use IEnumerable<T> when we can Iterate through collection using foreach() [duplicate]

This question already has answers here:
Can anyone explain IEnumerable and IEnumerator to me? [closed]
(16 answers)
Closed 7 days ago.
I want to know the exact place where we should use IEnumberable<T>
I know how IEnumerable<T> work and returns IEnumerator<T> and all that but the ultimate goal of IEnumerable<T> is to query the data from the collection isn't it? That is what we can already do using foreach() loop ? So when to use IEnumerable<T>? what is the actual practical scenario where the IEnumerable<T> is the only option to query the collection?
but the ultimate goal of IEnumerable<T> is to query the data from the collection isn't it?
No; the goal of IEnumerable<T> is to provide access to a sequence, which may or may not be a collection. The point being to abstract away what the underlying source is. It could be a raw collection, but it could be:
some LINQ (or similar) projection (collection.Where(...).Select(...) etc)
an open query to ADO.NET, redis, a socket, gRPC, a file or some other data provider that isn't readily countable, repeatable, etc - just: "a sequence"
an in-process data generator
some producer/consumer setup
etc
If you know you're always iterating a collection, then sure: feel free to use the concrete type, or ICollection<T>/IList<T> etc; but: not every sequence is a collection.

Is there any performance impact of calling ToList() multiple times? [duplicate]

This question already has answers here:
Is there a performance impact when calling ToList()?
(10 answers)
Closed 5 years ago.
I started working on a project and I have noticed that ToList() gets called multiple times and I think it is not really necessary and redundant.
The first ToList() is at the data layer where the call goes to database and gets the data.
public IEnumerable<Company> GetCompanies()
{
return DbContext.Companies.ToList();
}
Then at the controller I can see another call as ToList()
public ActionResult Index()
{
var companies = _companyService.GetCompanies().ToList();
return View(companies);
}
I believe that calling ToList() in the controller is redundant. But I just wonder whether it has any impact on performance or the language itself recognizes automatically that the result is actually is already list and ignores the second call?
Update
The other question asks if there is an impact calling ToList(). However, I wonder whether there is an impact calling the ToList() multiple times for the same list of objects. As someone mentioned that that should be "hopefully ignored".
Yes, there is a performance impact. Even if the underlying IEnumerable<T> is already a List<T> a call to ToList will cause new list to be created (so list != list.ToList()). Depending on the size of the original list, this may have serious performance implications

Difference between .Where(filter expression).FirstOrDefault() and .FirstOrDefault(filter expression) [duplicate]

This question already has answers here:
EF Where(x => x.ColumnVal == 1) vs FirstOrDefault(x => x.Column == 1)
(3 answers)
Closed 9 years ago.
in Entity Framework, what is the difference in doing:
db.Table.Where(filter).FirstOrDefault()
or
db.Table.FirstOrDefault(filter)
I guess that the first one applies the filter first and then take the first record. The second one get all records from table and then apply the filter, being more inefficient. Can you confirm me if this is correct or both are equivalent?
Best regards
There is none. They are equivalent.
Generally, though, you should keep the chaining to a minimum. Therefore the second is considered "correct".
These two have the same performance both in memory and in EF.
In memory, the first one obtains the results lazily, so it is not materially slower than the second one.
In EF or LINQ2SQL the query gets converted to SQL in its entirety, so only one result gets selected from the database in both instances. To see what is going on, enable SQL logging in EF, and observe that the generated SQL is identical.
The code with a separate Where is more typing, though, so the second form is preferred.

How to get the first element of IEnumerable (non-generic)? [duplicate]

This question already has answers here:
How to get the first element of IEnumerable
(5 answers)
Closed 9 years ago.
If I have a generic IEnumerable<int>. I can simply apply ToList() or ToArray() or FirstOrDefault() to it. How to apply these methods to a non-generic IEnumerable?
You have couple of options:
If you know that all objects in your enumerable are of the same type, you can cast it to the generic IEnumerable<YourType>. In worst case you can always use object:
object first = enumerable.Cast<object>().First();
Or you can use enumerator, make one step and take current element:
IEnumerator enumerator = enumerable.GetEnumerator();
enumerator.MoveNext();
object first = enumerator.Current;
You have two options here:
Follow the question that #Danier Gimenez suggested and make use of the Cast<TResult> method. After the cast you get a generic enumerable on which you can apply the First() method. This is also the most simple implementation.
Use the GetEnumerator() method which gives you an IEnumerator. And from here you can iterate over the collection. Starting with MoveNext(), you can use the Current property to get the first element.
Edit:
Andrei was ahead of me.
it is simple
look this sample code
IEnumerable collection;
--- fill collection here---
collection.OfType().ToList() or collection.OfType().ToArray
collection.OfType().ToList() or collection.OfType().ToArray()
it's filter the (int/MyClass) types object and convert it to a list or array

Detect unmaterialized LINQ Queries [duplicate]

This question already has answers here:
How to tell if an IEnumerable<T> is subject to deferred execution?
(6 answers)
Closed 9 years ago.
I have a Cache wrapper class that I use, which provides type safety and segmenting and other nice things.
I want to make it prevent me from shooting myself in the foot by caching an un-materialized LINQ query and only accept lists/collections...
Is there a way to detect if an IEnumerable is a LINQ query?
Maybe I'm answering my own question and should throw an exception when T is IEnumerable but not ICollection.
I would suggest just wrapping the IEnumerable<T> within your own collection, "materializing" it yourself.
This will provide full safety and more consistency, at the expense of potentially generating another collection instance and copying the references over.
You could always do a check for ICollection<T> and not regenerate, or similar, but there are still advantages to copying the contents into your own list. One major one is that you then control the one and only instance of the collection - you don't have to worry about another object adding or removing items (which may or may not be an issue, but is likely problematic for segmenting).

Categories