What I've noticed when using Select with an anonymous function or other value that's calculated at runtime is that every time you access the output IEnumerable object is that the projection recalculates the value. Example:
public class A
{
public string Name { get; set; }
public string Addr { get; set; }
}
public class B
{
public A Whatever {get;set;}
public int Id {get;set;}
}
Random rand = new Random();
IEnumerable<B> listOfBs = someListOfA.Select( x => new B()
{
Id = rand.Next(),
Whatever = x
});
What I've noticed is that every time I parse through the list listOfB and use the Id property, the Id is reevaluated with another rand.Next()
.
foreach( B b in listOfBs )
{
doSomething( b.Id );
}
I haven't seen what would cause this in the documentation on C# projections. Its almost as if Select generates an anonymous function that is reevaluated every time its accessed. So, two questions:
Let me know if my bad example code conveys my point.
It's expected and that's because most LINQ methods are lazy - that means they don't enumerate the source until results are needed. In you particular scenario listOfBs
is not really a materialized collection of B
objects. Instead, it's a definition on how to translate someListOfA
into a collection of B
objects. Select
returns an object which implements IEnumerable<T>
and stores both reference to the source collection and the projection delegate. The projection is done when results are needed, e.g. when you iterate over the collection in foreach
. If you iterate multiple times the projection will be performed multiple times. Which is exactly what you're seeing.
Call ToList
or ToArray
to materialize the results immediately:
IEnumerable<B> listOfBs = someListOfA.Select( x => new B()
{
Id = rand.Next(),
Whatever = x
}).ToList();